Version 2.13.0-30.0.dev

Merge commit 'b80ab44a537d30dea129cb8e918e1fb4a03a1272' into 'dev'
diff --git a/.dart_tool/package_config.json b/.dart_tool/package_config.json
index 29268f2..57799b3 100644
--- a/.dart_tool/package_config.json
+++ b/.dart_tool/package_config.json
@@ -11,7 +11,7 @@
     "constraint, update this by running tools/generate_package_config.dart."
   ],
   "configVersion": 2,
-  "generated": "2021-02-08T17:50:36.420568",
+  "generated": "2021-02-11T15:59:54.232365",
   "generator": "tools/generate_package_config.dart",
   "packages": [
     {
@@ -506,12 +506,24 @@
       "languageVersion": "2.12"
     },
     {
+      "name": "platform",
+      "rootUri": "../third_party/pkg/platform",
+      "packageUri": "lib/",
+      "languageVersion": "2.12"
+    },
+    {
       "name": "pool",
       "rootUri": "../third_party/pkg/pool",
       "packageUri": "lib/",
       "languageVersion": "2.12"
     },
     {
+      "name": "process",
+      "rootUri": "../third_party/pkg/process",
+      "packageUri": "lib/",
+      "languageVersion": "2.12"
+    },
+    {
       "name": "protobuf",
       "rootUri": "../third_party/pkg/protobuf/protobuf",
       "packageUri": "lib/",
@@ -782,4 +794,4 @@
       "languageVersion": "2.12"
     }
   ]
-}
+}
\ No newline at end of file
diff --git a/.packages b/.packages
index badd487..3587c4f 100644
--- a/.packages
+++ b/.packages
@@ -74,7 +74,9 @@
 package_config:third_party/pkg_tested/package_config/lib
 path:third_party/pkg/path/lib
 pedantic:third_party/pkg/pedantic/lib
+platform:third_party/pkg/platform/lib
 pool:third_party/pkg/pool/lib
+process:third_party/pkg/process/lib
 protobuf:third_party/pkg/protobuf/protobuf/lib
 pub:third_party/pkg/pub/lib
 pub_semver:third_party/pkg/pub_semver/lib
diff --git a/DEPS b/DEPS
index 19a424f..6318463 100644
--- a/DEPS
+++ b/DEPS
@@ -130,8 +130,10 @@
   "package_config_rev": "249af482de9ebabfc781bf10d6152c938e5ce45e",
   "path_rev": "407ab76187fade41c31e39c745b39661b710106c",
   "pedantic_rev": "df177f6ae531426aaf7bbf0121c90dc89d9c57bf",
+  "platform_rev": "c20e6fa315e9f8820e51c0ae721f63aff33b8e17",
   "ply_rev": "604b32590ffad5cbb82e4afef1d305512d06ae93",
   "pool_rev": "7abe634002a1ba8a0928eded086062f1307ccfae",
+  "process_rev": "56ece43b53b64c63ae51ec184b76bd5360c28d0b",
   "protobuf_rev": "0d03fd588df69e9863e2a2efc0059dee8f18d5b2",
   "pub_rev": "0e657414a472e74ca5dd76ae0db50cc060251dec",
   "pub_semver_rev": "f50d80ef10c4b2fa5f4c8878036a4d9342c0cc82",
@@ -387,10 +389,14 @@
       Var("dart_git") + "path.git" + "@" + Var("path_rev"),
   Var("dart_root") + "/third_party/pkg/pedantic":
       Var("dart_git") + "pedantic.git" + "@" + Var("pedantic_rev"),
+  Var("dart_root") + "/third_party/pkg/platform":
+       Var("dart_git") + "platform.dart.git" + "@" + Var("platform_rev"),
   Var("dart_root") + "/third_party/pkg/pool":
       Var("dart_git") + "pool.git" + "@" + Var("pool_rev"),
   Var("dart_root") + "/third_party/pkg/protobuf":
        Var("dart_git") + "protobuf.git" + "@" + Var("protobuf_rev"),
+  Var("dart_root") + "/third_party/pkg/process":
+       Var("dart_git") + "process.dart.git" + "@" + Var("process_rev"),
   Var("dart_root") + "/third_party/pkg/pub_semver":
       Var("dart_git") + "pub_semver.git" + "@" + Var("pub_semver_rev"),
   Var("dart_root") + "/third_party/pkg/pub":
diff --git a/pkg/vm_service/pubspec.yaml b/pkg/vm_service/pubspec.yaml
index 7760e11..82aae53 100644
--- a/pkg/vm_service/pubspec.yaml
+++ b/pkg/vm_service/pubspec.yaml
@@ -18,5 +18,6 @@
   mockito: ^5.0.0-nullsafety.1
   path: ^1.8.0
   pedantic: ^1.10.0-nullsafety.3
+  process: ^4.0.0
   pub_semver: ^2.0.0-nullsafety.0
   test: ^1.16.0-nullsafety.13
diff --git a/pkg/vm_service/test/async_generator_breakpoint_test.dart b/pkg/vm_service/test/async_generator_breakpoint_test.dart
index d4c20a7..fb999fc 100644
--- a/pkg/vm_service/test/async_generator_breakpoint_test.dart
+++ b/pkg/vm_service/test/async_generator_breakpoint_test.dart
@@ -102,5 +102,9 @@
 
 final tests = <IsolateTest>[testAsync];
 
-main([args = const <String>[]]) =>
-    runIsolateTests(args, tests, testeeConcurrent: testeeDo);
+main([args = const <String>[]]) => runIsolateTests(
+      args,
+      tests,
+      'async_generator_breakpoint_test.dart',
+      testeeConcurrent: testeeDo,
+    );
diff --git a/pkg/vm_service/test/async_next_test.dart b/pkg/vm_service/test/async_next_test.dart
index 1d7387f..fe23bf1 100644
--- a/pkg/vm_service/test/async_next_test.dart
+++ b/pkg/vm_service/test/async_next_test.dart
@@ -42,5 +42,9 @@
   resumeIsolate,
 ];
 
-main([args = const <String>[]]) =>
-    runIsolateTests(args, tests, testeeConcurrent: testMain);
+main([args = const <String>[]]) => runIsolateTests(
+      args,
+      tests,
+      'async_next_test.dart',
+      testeeConcurrent: testMain,
+    );
diff --git a/pkg/vm_service/test/async_scope_test.dart b/pkg/vm_service/test/async_scope_test.dart
index 5b8d262..9451c0a 100644
--- a/pkg/vm_service/test/async_scope_test.dart
+++ b/pkg/vm_service/test/async_scope_test.dart
@@ -70,5 +70,9 @@
   resumeIsolate,
 ];
 
-main([args = const <String>[]]) =>
-    runIsolateTests(args, tests, testeeConcurrent: testeeDo);
+main([args = const <String>[]]) => runIsolateTests(
+      args,
+      tests,
+      'async_scope_test.dart',
+      testeeConcurrent: testeeDo,
+    );
diff --git a/pkg/vm_service/test/async_single_step_exception_test.dart b/pkg/vm_service/test/async_single_step_exception_test.dart
index b616326..2e06ba7 100644
--- a/pkg/vm_service/test/async_single_step_exception_test.dart
+++ b/pkg/vm_service/test/async_single_step_exception_test.dart
@@ -78,5 +78,10 @@
   resumeIsolate
 ];
 
-main([args = const <String>[]]) => runIsolateTests(args, tests,
-    testeeConcurrent: testMain, extraArgs: extraDebuggingArgs);
+main([args = const <String>[]]) => runIsolateTests(
+      args,
+      tests,
+      'async_single_step_exception_test.dart',
+      testeeConcurrent: testMain,
+      extraArgs: extraDebuggingArgs,
+    );
diff --git a/pkg/vm_service/test/async_single_step_into_test.dart b/pkg/vm_service/test/async_single_step_into_test.dart
index 36dd15b..604e00b 100644
--- a/pkg/vm_service/test/async_single_step_into_test.dart
+++ b/pkg/vm_service/test/async_single_step_into_test.dart
@@ -43,5 +43,10 @@
   resumeIsolate
 ];
 
-main([args = const <String>[]]) => runIsolateTestsSynchronous(args, tests,
-    testeeConcurrent: testMain, extraArgs: extraDebuggingArgs);
+main([args = const <String>[]]) => runIsolateTestsSynchronous(
+      args,
+      tests,
+      'async_single_step_into_test.dart',
+      testeeConcurrent: testMain,
+      extraArgs: extraDebuggingArgs,
+    );
diff --git a/pkg/vm_service/test/async_single_step_out_test.dart b/pkg/vm_service/test/async_single_step_out_test.dart
index a0a3d83..1db5d67 100644
--- a/pkg/vm_service/test/async_single_step_out_test.dart
+++ b/pkg/vm_service/test/async_single_step_out_test.dart
@@ -56,5 +56,10 @@
   resumeIsolate
 ];
 
-main([args = const <String>[]]) => runIsolateTests(args, tests,
-    testeeConcurrent: testMain, extraArgs: extraDebuggingArgs);
+main([args = const <String>[]]) => runIsolateTests(
+      args,
+      tests,
+      'async_single_step_out_test.dart',
+      testeeConcurrent: testMain,
+      extraArgs: extraDebuggingArgs,
+    );
diff --git a/pkg/vm_service/test/async_star_single_step_into_test.dart b/pkg/vm_service/test/async_star_single_step_into_test.dart
index d2d730e..bf5c964 100644
--- a/pkg/vm_service/test/async_star_single_step_into_test.dart
+++ b/pkg/vm_service/test/async_star_single_step_into_test.dart
@@ -70,5 +70,10 @@
   resumeIsolate,
 ];
 
-main([args = const <String>[]]) => runIsolateTestsSynchronous(args, tests,
-    testeeConcurrent: testMain, extraArgs: extraDebuggingArgs);
+main([args = const <String>[]]) => runIsolateTestsSynchronous(
+      args,
+      tests,
+      'async_star_single_step_into_test.dart',
+      testeeConcurrent: testMain,
+      extraArgs: extraDebuggingArgs,
+    );
diff --git a/pkg/vm_service/test/async_star_step_out_test.dart b/pkg/vm_service/test/async_star_step_out_test.dart
index 5bb8dde..14a05f9 100644
--- a/pkg/vm_service/test/async_star_step_out_test.dart
+++ b/pkg/vm_service/test/async_star_step_out_test.dart
@@ -100,5 +100,10 @@
   stoppedAtLine(LINE_I), // return null.
 ];
 
-main([args = const <String>[]]) => runIsolateTestsSynchronous(args, tests,
-    testeeConcurrent: testMain, extraArgs: extraDebuggingArgs);
+main([args = const <String>[]]) => runIsolateTestsSynchronous(
+      args,
+      tests,
+      'async_star_step_out_test.dart',
+      testeeConcurrent: testMain,
+      extraArgs: extraDebuggingArgs,
+    );
diff --git a/pkg/vm_service/test/async_step_out_test.dart b/pkg/vm_service/test/async_step_out_test.dart
index 8e46584..e08ae35 100644
--- a/pkg/vm_service/test/async_step_out_test.dart
+++ b/pkg/vm_service/test/async_step_out_test.dart
@@ -53,5 +53,10 @@
   stoppedAtLine(LINE_F),
 ];
 
-main([args = const <String>[]]) => runIsolateTests(args, tests,
-    testeeConcurrent: testMain, extraArgs: extraDebuggingArgs);
+main([args = const <String>[]]) => runIsolateTests(
+      args,
+      tests,
+      'async_step_out_test.dart',
+      testeeConcurrent: testMain,
+      extraArgs: extraDebuggingArgs,
+    );
diff --git a/pkg/vm_service/test/common/test_helper.dart b/pkg/vm_service/test/common/test_helper.dart
index cd6a983..c589177 100644
--- a/pkg/vm_service/test/common/test_helper.dart
+++ b/pkg/vm_service/test/common/test_helper.dart
@@ -7,6 +7,7 @@
 import 'dart:async';
 import 'dart:convert';
 import 'dart:io' as io;
+import 'package:process/process.dart';
 import 'package:vm_service/vm_service_io.dart';
 import 'package:vm_service/vm_service.dart';
 import 'package:test/test.dart';
@@ -27,19 +28,15 @@
   return io.Platform.environment.containsKey(_TESTEE_ENV_KEY);
 }
 
-Uri _getTestUri() {
+Uri _getTestUri(String script) {
   if (io.Platform.script.scheme == 'data') {
-    // If we're using pub to run these tests this value isn't a file URI.
-    // We'll need to parse the actual URI out...
-    final fileRegExp = RegExp(r'file:\/\/\/.*\.dart');
-    final path =
-        fileRegExp.stringMatch(io.Platform.script.data!.contentAsString());
-    if (path == null) {
-      throw 'Unable to determine file path for script!';
-    }
-    return Uri.parse(path);
+    // If running from pub we can assume that we're in the root of the package
+    // directory.
+    return Uri.parse('test/$script');
   } else {
-    return io.Platform.script;
+    // Resolve the script to ensure that test will fail if the provided script
+    // name doesn't match the actual script.
+    return io.Platform.script.resolve(script);
   }
 }
 
@@ -97,7 +94,8 @@
   List<String> args;
   bool killedByTester = false;
 
-  _ServiceTesteeLauncher() : args = [_getTestUri().toFilePath()];
+  _ServiceTesteeLauncher(String script)
+      : args = [_getTestUri(script).toFilePath()];
 
   // Spawn the testee process.
   Future<io.Process> _spawnProcess(
@@ -164,7 +162,13 @@
       arguments.insert(0, '-D$k=$v');
     });
     print('** Launching $bashEnvironment$executable ${arguments.join(' ')}');
-    return io.Process.start(executable, arguments, environment: environment);
+    return LocalProcessManager().start(
+      [
+        executable,
+        ...arguments,
+      ],
+      environment: environment,
+    );
   }
 
   Future<Uri> launch(
@@ -214,10 +218,10 @@
         io.stdout.write('>testee>err> ${line}\n');
       });
       process!.exitCode.then((exitCode) {
-        if ((io.exitCode != 0) && !killedByTester) {
+        if ((exitCode != 0) && !killedByTester) {
           throw "Testee exited with $exitCode";
         }
-        print("** Process exited");
+        print("** Process exited: $exitCode");
       });
       return completer.future;
     });
@@ -245,13 +249,14 @@
       List<String>? extraArgs,
       List<VMTest>? vmTests,
       List<IsolateTest>? isolateTests,
+      required String scriptName,
       bool pause_on_start = false,
       bool pause_on_exit = false,
       bool verbose_vm = false,
       bool pause_on_unhandled_exceptions = false,
       bool testeeControlsServer = false,
       bool useAuthToken = false}) async {
-    var process = _ServiceTesteeLauncher();
+    var process = _ServiceTesteeLauncher(scriptName);
     late VmService vm;
     late IsolateRef isolate;
     setUp(() async {
@@ -272,7 +277,7 @@
       });
     });
 
-    final name = _getTestUri().pathSegments.last;
+    final name = _getTestUri(scriptName).pathSegments.last;
 
     test(
       name,
@@ -348,7 +353,8 @@
 /// to run tests or testee in this invocation of the script.
 Future<void> runIsolateTests(
   List<String> mainArgs,
-  List<IsolateTest> tests, {
+  List<IsolateTest> tests,
+  String scriptName, {
   testeeBefore()?,
   testeeConcurrent()?,
   bool pause_on_start = false,
@@ -369,6 +375,7 @@
   } else {
     await _ServiceTesterRunner().run(
         mainArgs: mainArgs,
+        scriptName: scriptName,
         extraArgs: extraArgs,
         isolateTests: tests,
         pause_on_start: pause_on_start,
@@ -391,7 +398,8 @@
 /// functions).
 void runIsolateTestsSynchronous(
   List<String> mainArgs,
-  List<IsolateTest> tests, {
+  List<IsolateTest> tests,
+  String scriptName, {
   void testeeBefore()?,
   void testeeConcurrent()?,
   bool pause_on_start = false,
@@ -410,6 +418,7 @@
   } else {
     _ServiceTesterRunner().run(
         mainArgs: mainArgs,
+        scriptName: scriptName,
         extraArgs: extraArgs,
         isolateTests: tests,
         pause_on_start: pause_on_start,
@@ -425,7 +434,8 @@
 /// to run tests or testee in this invocation of the script.
 Future<void> runVMTests(
   List<String> mainArgs,
-  List<VMTest> tests, {
+  List<VMTest> tests,
+  String scriptName, {
   testeeBefore()?,
   testeeConcurrent()?,
   bool pause_on_start = false,
@@ -443,6 +453,7 @@
   } else {
     await _ServiceTesterRunner().run(
         mainArgs: mainArgs,
+        scriptName: scriptName,
         extraArgs: extraArgs,
         vmTests: tests,
         pause_on_start: pause_on_start,
diff --git a/pkg/vm_service/test/coverage_leaf_function_test.dart b/pkg/vm_service/test/coverage_leaf_function_test.dart
index 1e5146f..fd15551 100644
--- a/pkg/vm_service/test/coverage_leaf_function_test.dart
+++ b/pkg/vm_service/test/coverage_leaf_function_test.dart
@@ -111,5 +111,9 @@
   },
 ];
 
-main([args = const <String>[]]) =>
-    runIsolateTests(args, tests, testeeConcurrent: testFunction);
+main([args = const <String>[]]) => runIsolateTests(
+      args,
+      tests,
+      'coverage_leaf_function_test.dart',
+      testeeConcurrent: testFunction,
+    );
diff --git a/pkg/vm_service/test/debugging_test.dart b/pkg/vm_service/test/debugging_test.dart
index 615dfc2..1ddee02 100644
--- a/pkg/vm_service/test/debugging_test.dart
+++ b/pkg/vm_service/test/debugging_test.dart
@@ -236,5 +236,9 @@
   },
 ];
 
-main([args = const <String>[]]) =>
-    runIsolateTests(args, tests, testeeBefore: startTimer);
+main([args = const <String>[]]) => runIsolateTests(
+      args,
+      tests,
+      'debugging_test.dart',
+      testeeBefore: startTimer,
+    );
diff --git a/pkg/vm_service/test/eval_test.dart b/pkg/vm_service/test/eval_test.dart
index 5be029f..a711697 100644
--- a/pkg/vm_service/test/eval_test.dart
+++ b/pkg/vm_service/test/eval_test.dart
@@ -109,5 +109,9 @@
   }
 }
 
-main([args = const <String>[]]) =>
-    runIsolateTests(args, tests, testeeConcurrent: testFunction);
+main([args = const <String>[]]) => runIsolateTests(
+      args,
+      tests,
+      'eval_test.dart',
+      testeeConcurrent: testFunction,
+    );
diff --git a/pkg/vm_service/test/evaluate_with_scope_test.dart b/pkg/vm_service/test/evaluate_with_scope_test.dart
index 54e8979..a10aeee 100644
--- a/pkg/vm_service/test/evaluate_with_scope_test.dart
+++ b/pkg/vm_service/test/evaluate_with_scope_test.dart
@@ -62,5 +62,9 @@
   }
 ];
 
-main([args = const <String>[]]) =>
-    runIsolateTests(args, tests, testeeBefore: testeeMain);
+main([args = const <String>[]]) => runIsolateTests(
+      args,
+      tests,
+      'evaluate_with_scope_test.dart',
+      testeeBefore: testeeMain,
+    );
diff --git a/pkg/vm_service/test/file_service_test.dart b/pkg/vm_service/test/file_service_test.dart
index 045ba1e..e8b5713 100644
--- a/pkg/vm_service/test/file_service_test.dart
+++ b/pkg/vm_service/test/file_service_test.dart
@@ -111,4 +111,9 @@
   },
 ];
 
-main(args) async => runIsolateTests(args, fileTests, testeeBefore: setupFiles);
+main([args = const <String>[]]) async => runIsolateTests(
+      args,
+      fileTests,
+      'file_service_test.dart',
+      testeeBefore: setupFiles,
+    );
diff --git a/pkg/vm_service/test/get_allocation_profile_rpc_test.dart b/pkg/vm_service/test/get_allocation_profile_rpc_test.dart
index 4ce9675..3007013 100644
--- a/pkg/vm_service/test/get_allocation_profile_rpc_test.dart
+++ b/pkg/vm_service/test/get_allocation_profile_rpc_test.dart
@@ -65,4 +65,8 @@
   },
 ];
 
-main([args = const <String>[]]) async => runIsolateTests(args, tests);
+main([args = const <String>[]]) async => runIsolateTests(
+      args,
+      tests,
+      'get_allocation_profile_rpc_test.dart',
+    );
diff --git a/pkg/vm_service/test/get_cpu_samples_rpc_test.dart b/pkg/vm_service/test/get_cpu_samples_rpc_test.dart
index 95d8c85..d90c2f8 100644
--- a/pkg/vm_service/test/get_cpu_samples_rpc_test.dart
+++ b/pkg/vm_service/test/get_cpu_samples_rpc_test.dart
@@ -56,5 +56,10 @@
   '--profile-vm=false', // So this also works with KBC.
 ];
 
-main([args = const <String>[]]) async =>
-    runIsolateTests(args, tests, testeeBefore: testeeDo, extraArgs: vmArgs);
+main([args = const <String>[]]) async => runIsolateTests(
+      args,
+      tests,
+      'get_cpu_samples_rpc_test.dart',
+      testeeBefore: testeeDo,
+      extraArgs: vmArgs,
+    );
diff --git a/pkg/vm_service/test/get_flag_list_rpc_test.dart b/pkg/vm_service/test/get_flag_list_rpc_test.dart
index 1fba955..ef3f5ad 100644
--- a/pkg/vm_service/test/get_flag_list_rpc_test.dart
+++ b/pkg/vm_service/test/get_flag_list_rpc_test.dart
@@ -72,4 +72,8 @@
   }
 ];
 
-main([args = const <String>[]]) async => runVMTests(args, tests);
+main([args = const <String>[]]) async => runVMTests(
+      args,
+      tests,
+      'get_flag_list_rpc_test.dart',
+    );
diff --git a/pkg/vm_service/test/get_isolate_group_memory_usage.dart b/pkg/vm_service/test/get_isolate_group_memory_usage.dart
index 6ab44e5..dcef7b4 100644
--- a/pkg/vm_service/test/get_isolate_group_memory_usage.dart
+++ b/pkg/vm_service/test/get_isolate_group_memory_usage.dart
@@ -32,4 +32,8 @@
   },
 ];
 
-main(args) async => runVMTests(args, tests);
+main(args) async => runVMTests(
+      args,
+      tests,
+      'get_isolate_group_memory_usage.dart',
+    );
diff --git a/pkg/vm_service/test/get_isolate_rpc_test.dart b/pkg/vm_service/test/get_isolate_rpc_test.dart
index 29e3d7a..af7232d 100644
--- a/pkg/vm_service/test/get_isolate_rpc_test.dart
+++ b/pkg/vm_service/test/get_isolate_rpc_test.dart
@@ -55,4 +55,8 @@
   },
 ];
 
-main(args) async => runVMTests(args, tests);
+main([args = const <String>[]]) async => runVMTests(
+      args,
+      tests,
+      'get_isolate_rpc_test.dart',
+    );
diff --git a/pkg/vm_service/test/get_memory_usage.dart b/pkg/vm_service/test/get_memory_usage_test.dart
similarity index 88%
rename from pkg/vm_service/test/get_memory_usage.dart
rename to pkg/vm_service/test/get_memory_usage_test.dart
index 9325f59..ccaea5c 100644
--- a/pkg/vm_service/test/get_memory_usage.dart
+++ b/pkg/vm_service/test/get_memory_usage_test.dart
@@ -29,4 +29,8 @@
   },
 ];
 
-main(args) async => runVMTests(args, tests);
+main([args = const <String>[]]) async => runVMTests(
+      args,
+      tests,
+      'get_memory_usage_test.dart',
+    );
diff --git a/pkg/vm_service/test/get_stack_test.dart b/pkg/vm_service/test/get_stack_test.dart
index 28c5001..77c3595 100644
--- a/pkg/vm_service/test/get_stack_test.dart
+++ b/pkg/vm_service/test/get_stack_test.dart
@@ -144,5 +144,9 @@
   },
 ];
 
-main([args = const <String>[]]) =>
-    runIsolateTests(args, tests, testeeConcurrent: testMain);
+main([args = const <String>[]]) => runIsolateTests(
+      args,
+      tests,
+      'get_stack_test.dart',
+      testeeConcurrent: testMain,
+    );
diff --git a/pkg/vm_service/test/get_version_rpc_test.dart b/pkg/vm_service/test/get_version_rpc_test.dart
index 3cfedda..57be153 100644
--- a/pkg/vm_service/test/get_version_rpc_test.dart
+++ b/pkg/vm_service/test/get_version_rpc_test.dart
@@ -15,4 +15,8 @@
   },
 ];
 
-main([args = const <String>[]]) async => await runVMTests(args, tests);
+main([args = const <String>[]]) async => await runVMTests(
+      args,
+      tests,
+      'get_version_rpc_test.dart',
+    );
diff --git a/pkg/vm_service/test/heap_snapshot_graph_test.dart b/pkg/vm_service/test/heap_snapshot_graph_test.dart
index 51490ec..f04961a 100644
--- a/pkg/vm_service/test/heap_snapshot_graph_test.dart
+++ b/pkg/vm_service/test/heap_snapshot_graph_test.dart
@@ -105,5 +105,9 @@
   },
 ];
 
-main([args = const <String>[]]) async =>
-    runIsolateTests(args, tests, testeeBefore: script);
+main([args = const <String>[]]) async => runIsolateTests(
+      args,
+      tests,
+      'heap_snapshot_graph_test.dart',
+      testeeBefore: script,
+    );
diff --git a/pkg/vm_service/test/http_enable_timeline_logging_service_test.dart b/pkg/vm_service/test/http_enable_timeline_logging_service_test.dart
index 2bbc902..1341f1a 100644
--- a/pkg/vm_service/test/http_enable_timeline_logging_service_test.dart
+++ b/pkg/vm_service/test/http_enable_timeline_logging_service_test.dart
@@ -87,5 +87,9 @@
   },
 ];
 
-main([args = const <String>[]]) async =>
-    runIsolateTests(args, tests, testeeBefore: setup);
+main([args = const <String>[]]) async => runIsolateTests(
+      args,
+      tests,
+      'http_enable_timeline_logging_service_test.dart',
+      testeeBefore: setup,
+    );
diff --git a/pkg/vm_service/test/invoke_test.dart b/pkg/vm_service/test/invoke_test.dart
index 6458f97d..e4c7f1f 100644
--- a/pkg/vm_service/test/invoke_test.dart
+++ b/pkg/vm_service/test/invoke_test.dart
@@ -75,5 +75,9 @@
   expect(result.type == 'Error' || result.type == '@Error', isTrue);
 }
 
-main([args = const <String>[]]) =>
-    runIsolateTests(args, tests, testeeConcurrent: testFunction);
+main([args = const <String>[]]) => runIsolateTests(
+      args,
+      tests,
+      'invoke_test.dart',
+      testeeConcurrent: testFunction,
+    );
diff --git a/pkg/vm_service/test/network_profiling_test.dart b/pkg/vm_service/test/network_profiling_test.dart
index b993389..21757ad 100644
--- a/pkg/vm_service/test/network_profiling_test.dart
+++ b/pkg/vm_service/test/network_profiling_test.dart
@@ -130,5 +130,9 @@
   // TODO(bkonyi): fully port observatory test for socket profiling.
 ];
 
-main([args = const <String>[]]) async =>
-    runIsolateTests(args, tests, testeeBefore: setup);
+main([args = const <String>[]]) async => runIsolateTests(
+      args,
+      tests,
+      'network_profiling_test.dart',
+      testeeBefore: setup,
+    );
diff --git a/pkg/vm_service/test/object_graph_identity_hash_test.dart b/pkg/vm_service/test/object_graph_identity_hash_test.dart
index da61a9d..15d59ee 100644
--- a/pkg/vm_service/test/object_graph_identity_hash_test.dart
+++ b/pkg/vm_service/test/object_graph_identity_hash_test.dart
@@ -151,9 +151,10 @@
   },
 ];
 
-main(args) => runIsolateTests(
+main([args = const <String>[]]) => runIsolateTests(
       args,
       tests,
+      'object_graph_identity_hash_test.dart',
       testeeBefore: script,
       pause_on_exit: true,
     );
diff --git a/pkg/vm_service/test/process_service_test.dart b/pkg/vm_service/test/process_service_test.dart
index b1c269a..7fa9aba 100644
--- a/pkg/vm_service/test/process_service_test.dart
+++ b/pkg/vm_service/test/process_service_test.dart
@@ -7,15 +7,12 @@
 import 'dart:developer';
 import 'dart:io' as io;
 
-import 'package:path/path.dart' as path;
+import 'package:process/process.dart';
 import 'package:test/test.dart';
 import 'package:vm_service/vm_service.dart';
 
 import 'common/test_helper.dart';
 
-final dartJITBinary = path.join(path.dirname(io.Platform.resolvedExecutable),
-    'dart' + path.extension(io.Platform.resolvedExecutable));
-
 Future setupProcesses() async {
   final dir = await io.Directory.systemTemp.createTemp('file_service');
 
@@ -48,10 +45,15 @@
   }
 
   Future<ServiceExtensionResponse> setup(ignored_a, ignored_b) async {
+    final processManager = LocalProcessManager();
     try {
-      process1 = await io.Process.start(io.Platform.executable, args);
-      process2 =
-          await io.Process.start(io.Platform.executable, args..add('foobar'));
+      process1 = await processManager.start(
+        [io.Platform.resolvedExecutable, ...args],
+      );
+      process2 = await processManager.start([
+        io.Platform.resolvedExecutable,
+        ...(args..add('foobar')),
+      ]);
       final codeFilePath = dir.path + io.Platform.pathSeparator + "other_file";
       final codeFile = io.File(codeFilePath);
       await codeFile.writeAsString('''
@@ -61,8 +63,13 @@
             await stdin.drain();
           }
           ''');
-      process3 = await io.Process.start(
-          dartJITBinary, [...io.Platform.executableArguments, codeFilePath]);
+      process3 = await processManager.start(
+        [
+          io.Platform.resolvedExecutable,
+          ...io.Platform.executableArguments,
+          codeFilePath
+        ],
+      );
     } catch (_) {
       closeDown();
       rethrow;
@@ -105,7 +112,7 @@
         all.processes[0].id,
       );
 
-      expect(first.name, io.Platform.executable);
+      expect(io.Platform.resolvedExecutable, contains(first.name.trim()));
       expect(first.pid, equals(setup.json!['pids']![0]));
       expect(first.arguments.contains('foobar'), isFalse);
       expect(first.startedAt, greaterThan(0));
@@ -115,7 +122,7 @@
         all.processes[1].id,
       );
 
-      expect(second.name, io.Platform.executable);
+      expect(io.Platform.resolvedExecutable, contains(second.name.trim()));
       expect(second.pid, equals(setup.json!['pids']![1]));
       expect(second.arguments.contains('foobar'), isTrue);
       expect(second.pid != first.pid, isTrue);
@@ -127,7 +134,7 @@
         all.processes[2].id,
       );
 
-      expect(third.name, dartJITBinary);
+      expect(io.Platform.resolvedExecutable, contains(third.name.trim()));
       expect(third.pid, equals(setup.json!['pids']![2]));
       expect(third.pid != first.pid, isTrue);
       expect(third.pid != second.pid, isTrue);
@@ -148,5 +155,9 @@
   },
 ];
 
-main(args) async =>
-    runIsolateTests(args, processTests, testeeBefore: setupProcesses);
+main([args = const <String>[]]) async => runIsolateTests(
+      args,
+      processTests,
+      'process_service_test.dart',
+      testeeBefore: setupProcesses,
+    );
diff --git a/pkg/vm_service/test/regress_44588_test.dart b/pkg/vm_service/test/regress_44588_test.dart
index 3469305..3f0564f 100644
--- a/pkg/vm_service/test/regress_44588_test.dart
+++ b/pkg/vm_service/test/regress_44588_test.dart
@@ -24,4 +24,8 @@
   }
 ];
 
-main([args = const <String>[]]) => runIsolateTests(args, tests);
+main([args = const <String>[]]) => runIsolateTests(
+      args,
+      tests,
+      'regress_44588_test.dart',
+    );
diff --git a/pkg/vm_service/test/throws_sentinel_test.dart b/pkg/vm_service/test/throws_sentinel_test.dart
index 623ab02..3b377c5 100644
--- a/pkg/vm_service/test/throws_sentinel_test.dart
+++ b/pkg/vm_service/test/throws_sentinel_test.dart
@@ -20,4 +20,8 @@
   },
 ];
 
-main([args = const <String>[]]) async => await runVMTests(args, tests);
+main([args = const <String>[]]) async => await runVMTests(
+      args,
+      tests,
+      'throws_sentinel_test.dart',
+    );
diff --git a/runtime/vm/class_table.cc b/runtime/vm/class_table.cc
index 248cf45..3f1274c 100644
--- a/runtime/vm/class_table.cc
+++ b/runtime/vm/class_table.cc
@@ -72,10 +72,11 @@
 }
 
 void ClassTable::set_table(ClassPtr* table) {
-  Isolate* isolate = Isolate::Current();
-  ASSERT(isolate != nullptr);
+  // We don't have to stop mutators, since the old table is the prefix of the
+  // new table. But we should ensure that all writes to the current table are
+  // visible once the new table is visible.
   table_.store(table);
-  isolate->set_cached_class_table_table(table);
+  IsolateGroup::Current()->set_cached_class_table_table(table);
 }
 
 ClassTable::ClassTable(SharedClassTable* shared_class_table)
diff --git a/runtime/vm/class_table.h b/runtime/vm/class_table.h
index 3660e29..9f23820 100644
--- a/runtime/vm/class_table.h
+++ b/runtime/vm/class_table.h
@@ -420,7 +420,7 @@
   friend Isolate* CreateWithinExistingIsolateGroup(IsolateGroup* group,
                                                    const char* name,
                                                    char** error);
-  friend class Isolate;  // for table()
+  friend class IsolateGroup;  // for table()
   static const int kInitialCapacity = SharedClassTable::kInitialCapacity;
   static const int kCapacityIncrement = SharedClassTable::kCapacityIncrement;
 
diff --git a/runtime/vm/compiler/aot/precompiler.cc b/runtime/vm/compiler/aot/precompiler.cc
index 50a67e9..2c1ebd4 100644
--- a/runtime/vm/compiler/aot/precompiler.cc
+++ b/runtime/vm/compiler/aot/precompiler.cc
@@ -57,7 +57,6 @@
 namespace dart {
 
 #define T (thread())
-#define I (isolate())
 #define IG (isolate_group())
 #define Z (zone())
 
@@ -1004,7 +1003,8 @@
   fields_to_retain_.Insert(&Field::ZoneHandle(Z, field.ptr()));
 
   if (field.is_static()) {
-    const Object& value = Object::Handle(Z, field.StaticValue());
+    const Object& value =
+        Object::Handle(Z, IG->initial_field_table()->At(field.field_id()));
     // Should not be in the middle of initialization while precompiling.
     ASSERT(value.ptr() != Object::transition_sentinel().ptr());
 
@@ -2878,6 +2878,8 @@
                                       Thread* thread,
                                       Zone* zone,
                                       const Function& function) {
+  NoActiveIsolateScope no_isolate_scope;
+
   VMTagScope tagScope(thread, VMTag::kCompileUnoptimizedTagId);
   TIMELINE_FUNCTION_COMPILATION_DURATION(thread, "CompileFunction", function);
 
diff --git a/runtime/vm/compiler/assembler/assembler_arm.cc b/runtime/vm/compiler/assembler/assembler_arm.cc
index 8bad1fc..42d0440 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm.cc
@@ -2024,9 +2024,9 @@
   ASSERT(result != class_id);
 
   const intptr_t table_offset =
-      target::Isolate::cached_class_table_table_offset();
+      target::IsolateGroup::cached_class_table_table_offset();
 
-  LoadIsolate(result);
+  LoadIsolateGroup(result);
   LoadFromOffset(result, result, table_offset);
   ldr(result, Address(result, class_id, LSL, target::kWordSizeLog2));
 }
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.cc b/runtime/vm/compiler/assembler/assembler_arm64.cc
index f1d8195..af87467 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm64.cc
@@ -1188,9 +1188,9 @@
   ASSERT(result != class_id);
 
   const intptr_t table_offset =
-      target::Isolate::cached_class_table_table_offset();
+      target::IsolateGroup::cached_class_table_table_offset();
 
-  LoadIsolate(result);
+  LoadIsolateGroup(result);
   LoadFromOffset(result, result, table_offset);
   ldr(result, Address(result, class_id, UXTX, Address::Scaled));
 }
diff --git a/runtime/vm/compiler/assembler/assembler_ia32.cc b/runtime/vm/compiler/assembler/assembler_ia32.cc
index 7c5abdd..c845d8a 100644
--- a/runtime/vm/compiler/assembler/assembler_ia32.cc
+++ b/runtime/vm/compiler/assembler/assembler_ia32.cc
@@ -2709,8 +2709,8 @@
   ASSERT(result != class_id);
 
   const intptr_t table_offset =
-      target::Isolate::cached_class_table_table_offset();
-  LoadIsolate(result);
+      target::IsolateGroup::cached_class_table_table_offset();
+  LoadIsolateGroup(result);
   movl(result, Address(result, table_offset));
   movl(result, Address(result, class_id, TIMES_4, 0));
 }
diff --git a/runtime/vm/compiler/assembler/assembler_x64.cc b/runtime/vm/compiler/assembler/assembler_x64.cc
index c089993..03122d3 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.cc
+++ b/runtime/vm/compiler/assembler/assembler_x64.cc
@@ -2193,9 +2193,9 @@
 void Assembler::LoadClassById(Register result, Register class_id) {
   ASSERT(result != class_id);
   const intptr_t table_offset =
-      target::Isolate::cached_class_table_table_offset();
+      target::IsolateGroup::cached_class_table_table_offset();
 
-  LoadIsolate(result);
+  LoadIsolateGroup(result);
   movq(result, Address(result, table_offset));
   movq(result, Address(result, class_id, TIMES_8, 0));
 }
diff --git a/runtime/vm/compiler/jit/compiler.cc b/runtime/vm/compiler/jit/compiler.cc
index 92c90ce..3799ebd 100644
--- a/runtime/vm/compiler/jit/compiler.cc
+++ b/runtime/vm/compiler/jit/compiler.cc
@@ -631,7 +631,11 @@
 
 #if !defined(PRODUCT)
         if (!function.HasOptimizedCode()) {
-          isolate()->debugger()->NotifyCompilation(function);
+          // TODO(dartbug.com/36097): We might need to adjust this once we start
+          // adding debugging support to --enable-isolate-groups.
+          thread()->isolate_group()->ForEachIsolate([&](Isolate* isolate) {
+            isolate->debugger()->NotifyCompilation(function);
+          });
         }
 #endif
         if (FLAG_disassemble && FlowGraphPrinter::ShouldPrint(function)) {
diff --git a/runtime/vm/compiler/runtime_api.h b/runtime/vm/compiler/runtime_api.h
index f135cff..2160708 100644
--- a/runtime/vm/compiler/runtime_api.h
+++ b/runtime/vm/compiler/runtime_api.h
@@ -1151,7 +1151,6 @@
   static word default_tag_offset();
   static word current_tag_offset();
   static word user_tag_offset();
-  static word cached_class_table_table_offset();
   static word ic_miss_code_offset();
 #if !defined(PRODUCT)
   static word single_step_offset();
@@ -1161,6 +1160,7 @@
 class IsolateGroup : public AllStatic {
  public:
   static word shared_class_table_offset();
+  static word cached_class_table_table_offset();
 };
 
 class SharedClassTable : public AllStatic {
diff --git a/runtime/vm/compiler/runtime_offsets_extracted.h b/runtime/vm/compiler/runtime_offsets_extracted.h
index b7cf933..94dc8ed 100644
--- a/runtime/vm/compiler/runtime_offsets_extracted.h
+++ b/runtime/vm/compiler/runtime_offsets_extracted.h
@@ -165,8 +165,6 @@
 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 Int32x4_value_offset = 8;
-static constexpr dart::compiler::target::word
-    Isolate_cached_class_table_table_offset = 36;
 static constexpr dart::compiler::target::word Isolate_current_tag_offset = 20;
 static constexpr dart::compiler::target::word Isolate_default_tag_offset = 24;
 static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 28;
@@ -174,7 +172,9 @@
     Isolate_cached_object_store_offset = 32;
 static constexpr dart::compiler::target::word
     IsolateGroup_shared_class_table_offset = 8;
-static constexpr dart::compiler::target::word Isolate_single_step_offset = 44;
+static constexpr dart::compiler::target::word
+    IsolateGroup_cached_class_table_table_offset = 16;
+static constexpr dart::compiler::target::word Isolate_single_step_offset = 40;
 static constexpr dart::compiler::target::word Isolate_user_tag_offset = 16;
 static constexpr dart::compiler::target::word LinkedHashMap_data_offset = 16;
 static constexpr dart::compiler::target::word
@@ -698,8 +698,6 @@
 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 Int32x4_value_offset = 8;
-static constexpr dart::compiler::target::word
-    Isolate_cached_class_table_table_offset = 72;
 static constexpr dart::compiler::target::word Isolate_current_tag_offset = 40;
 static constexpr dart::compiler::target::word Isolate_default_tag_offset = 48;
 static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 56;
@@ -707,7 +705,9 @@
     Isolate_cached_object_store_offset = 64;
 static constexpr dart::compiler::target::word
     IsolateGroup_shared_class_table_offset = 16;
-static constexpr dart::compiler::target::word Isolate_single_step_offset = 88;
+static constexpr dart::compiler::target::word
+    IsolateGroup_cached_class_table_table_offset = 32;
+static constexpr dart::compiler::target::word Isolate_single_step_offset = 80;
 static constexpr dart::compiler::target::word Isolate_user_tag_offset = 32;
 static constexpr dart::compiler::target::word LinkedHashMap_data_offset = 32;
 static constexpr dart::compiler::target::word
@@ -1236,8 +1236,6 @@
 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 Int32x4_value_offset = 8;
-static constexpr dart::compiler::target::word
-    Isolate_cached_class_table_table_offset = 36;
 static constexpr dart::compiler::target::word Isolate_current_tag_offset = 20;
 static constexpr dart::compiler::target::word Isolate_default_tag_offset = 24;
 static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 28;
@@ -1245,7 +1243,9 @@
     Isolate_cached_object_store_offset = 32;
 static constexpr dart::compiler::target::word
     IsolateGroup_shared_class_table_offset = 8;
-static constexpr dart::compiler::target::word Isolate_single_step_offset = 44;
+static constexpr dart::compiler::target::word
+    IsolateGroup_cached_class_table_table_offset = 16;
+static constexpr dart::compiler::target::word Isolate_single_step_offset = 40;
 static constexpr dart::compiler::target::word Isolate_user_tag_offset = 16;
 static constexpr dart::compiler::target::word LinkedHashMap_data_offset = 16;
 static constexpr dart::compiler::target::word
@@ -1766,8 +1766,6 @@
 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 Int32x4_value_offset = 8;
-static constexpr dart::compiler::target::word
-    Isolate_cached_class_table_table_offset = 72;
 static constexpr dart::compiler::target::word Isolate_current_tag_offset = 40;
 static constexpr dart::compiler::target::word Isolate_default_tag_offset = 48;
 static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 56;
@@ -1775,7 +1773,9 @@
     Isolate_cached_object_store_offset = 64;
 static constexpr dart::compiler::target::word
     IsolateGroup_shared_class_table_offset = 16;
-static constexpr dart::compiler::target::word Isolate_single_step_offset = 88;
+static constexpr dart::compiler::target::word
+    IsolateGroup_cached_class_table_table_offset = 32;
+static constexpr dart::compiler::target::word Isolate_single_step_offset = 80;
 static constexpr dart::compiler::target::word Isolate_user_tag_offset = 32;
 static constexpr dart::compiler::target::word LinkedHashMap_data_offset = 32;
 static constexpr dart::compiler::target::word
@@ -2307,8 +2307,6 @@
 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 Int32x4_value_offset = 8;
-static constexpr dart::compiler::target::word
-    Isolate_cached_class_table_table_offset = 72;
 static constexpr dart::compiler::target::word Isolate_current_tag_offset = 40;
 static constexpr dart::compiler::target::word Isolate_default_tag_offset = 48;
 static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 56;
@@ -2316,7 +2314,9 @@
     Isolate_cached_object_store_offset = 64;
 static constexpr dart::compiler::target::word
     IsolateGroup_shared_class_table_offset = 16;
-static constexpr dart::compiler::target::word Isolate_single_step_offset = 88;
+static constexpr dart::compiler::target::word
+    IsolateGroup_cached_class_table_table_offset = 32;
+static constexpr dart::compiler::target::word Isolate_single_step_offset = 80;
 static constexpr dart::compiler::target::word Isolate_user_tag_offset = 32;
 static constexpr dart::compiler::target::word LinkedHashMap_data_offset = 32;
 static constexpr dart::compiler::target::word
@@ -2847,8 +2847,6 @@
 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 Int32x4_value_offset = 8;
-static constexpr dart::compiler::target::word
-    Isolate_cached_class_table_table_offset = 72;
 static constexpr dart::compiler::target::word Isolate_current_tag_offset = 40;
 static constexpr dart::compiler::target::word Isolate_default_tag_offset = 48;
 static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 56;
@@ -2856,7 +2854,9 @@
     Isolate_cached_object_store_offset = 64;
 static constexpr dart::compiler::target::word
     IsolateGroup_shared_class_table_offset = 16;
-static constexpr dart::compiler::target::word Isolate_single_step_offset = 88;
+static constexpr dart::compiler::target::word
+    IsolateGroup_cached_class_table_table_offset = 32;
+static constexpr dart::compiler::target::word Isolate_single_step_offset = 80;
 static constexpr dart::compiler::target::word Isolate_user_tag_offset = 32;
 static constexpr dart::compiler::target::word LinkedHashMap_data_offset = 32;
 static constexpr dart::compiler::target::word
@@ -3386,8 +3386,6 @@
 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 Int32x4_value_offset = 8;
-static constexpr dart::compiler::target::word
-    Isolate_cached_class_table_table_offset = 36;
 static constexpr dart::compiler::target::word Isolate_current_tag_offset = 20;
 static constexpr dart::compiler::target::word Isolate_default_tag_offset = 24;
 static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 28;
@@ -3395,6 +3393,8 @@
     Isolate_cached_object_store_offset = 32;
 static constexpr dart::compiler::target::word
     IsolateGroup_shared_class_table_offset = 8;
+static constexpr dart::compiler::target::word
+    IsolateGroup_cached_class_table_table_offset = 16;
 static constexpr dart::compiler::target::word Isolate_user_tag_offset = 16;
 static constexpr dart::compiler::target::word LinkedHashMap_data_offset = 16;
 static constexpr dart::compiler::target::word
@@ -3913,8 +3913,6 @@
 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 Int32x4_value_offset = 8;
-static constexpr dart::compiler::target::word
-    Isolate_cached_class_table_table_offset = 72;
 static constexpr dart::compiler::target::word Isolate_current_tag_offset = 40;
 static constexpr dart::compiler::target::word Isolate_default_tag_offset = 48;
 static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 56;
@@ -3922,6 +3920,8 @@
     Isolate_cached_object_store_offset = 64;
 static constexpr dart::compiler::target::word
     IsolateGroup_shared_class_table_offset = 16;
+static constexpr dart::compiler::target::word
+    IsolateGroup_cached_class_table_table_offset = 32;
 static constexpr dart::compiler::target::word Isolate_user_tag_offset = 32;
 static constexpr dart::compiler::target::word LinkedHashMap_data_offset = 32;
 static constexpr dart::compiler::target::word
@@ -4445,8 +4445,6 @@
 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 Int32x4_value_offset = 8;
-static constexpr dart::compiler::target::word
-    Isolate_cached_class_table_table_offset = 36;
 static constexpr dart::compiler::target::word Isolate_current_tag_offset = 20;
 static constexpr dart::compiler::target::word Isolate_default_tag_offset = 24;
 static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 28;
@@ -4454,6 +4452,8 @@
     Isolate_cached_object_store_offset = 32;
 static constexpr dart::compiler::target::word
     IsolateGroup_shared_class_table_offset = 8;
+static constexpr dart::compiler::target::word
+    IsolateGroup_cached_class_table_table_offset = 16;
 static constexpr dart::compiler::target::word Isolate_user_tag_offset = 16;
 static constexpr dart::compiler::target::word LinkedHashMap_data_offset = 16;
 static constexpr dart::compiler::target::word
@@ -4969,8 +4969,6 @@
 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 Int32x4_value_offset = 8;
-static constexpr dart::compiler::target::word
-    Isolate_cached_class_table_table_offset = 72;
 static constexpr dart::compiler::target::word Isolate_current_tag_offset = 40;
 static constexpr dart::compiler::target::word Isolate_default_tag_offset = 48;
 static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 56;
@@ -4978,6 +4976,8 @@
     Isolate_cached_object_store_offset = 64;
 static constexpr dart::compiler::target::word
     IsolateGroup_shared_class_table_offset = 16;
+static constexpr dart::compiler::target::word
+    IsolateGroup_cached_class_table_table_offset = 32;
 static constexpr dart::compiler::target::word Isolate_user_tag_offset = 32;
 static constexpr dart::compiler::target::word LinkedHashMap_data_offset = 32;
 static constexpr dart::compiler::target::word
@@ -5504,8 +5504,6 @@
 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 Int32x4_value_offset = 8;
-static constexpr dart::compiler::target::word
-    Isolate_cached_class_table_table_offset = 72;
 static constexpr dart::compiler::target::word Isolate_current_tag_offset = 40;
 static constexpr dart::compiler::target::word Isolate_default_tag_offset = 48;
 static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 56;
@@ -5513,6 +5511,8 @@
     Isolate_cached_object_store_offset = 64;
 static constexpr dart::compiler::target::word
     IsolateGroup_shared_class_table_offset = 16;
+static constexpr dart::compiler::target::word
+    IsolateGroup_cached_class_table_table_offset = 32;
 static constexpr dart::compiler::target::word Isolate_user_tag_offset = 32;
 static constexpr dart::compiler::target::word LinkedHashMap_data_offset = 32;
 static constexpr dart::compiler::target::word
@@ -6038,8 +6038,6 @@
 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 Int32x4_value_offset = 8;
-static constexpr dart::compiler::target::word
-    Isolate_cached_class_table_table_offset = 72;
 static constexpr dart::compiler::target::word Isolate_current_tag_offset = 40;
 static constexpr dart::compiler::target::word Isolate_default_tag_offset = 48;
 static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 56;
@@ -6047,6 +6045,8 @@
     Isolate_cached_object_store_offset = 64;
 static constexpr dart::compiler::target::word
     IsolateGroup_shared_class_table_offset = 16;
+static constexpr dart::compiler::target::word
+    IsolateGroup_cached_class_table_table_offset = 32;
 static constexpr dart::compiler::target::word Isolate_user_tag_offset = 32;
 static constexpr dart::compiler::target::word LinkedHashMap_data_offset = 32;
 static constexpr dart::compiler::target::word
@@ -6581,8 +6581,6 @@
 static constexpr dart::compiler::target::word AOT_ICData_owner_offset = 16;
 static constexpr dart::compiler::target::word AOT_ICData_state_bits_offset = 20;
 static constexpr dart::compiler::target::word AOT_Int32x4_value_offset = 8;
-static constexpr dart::compiler::target::word
-    AOT_Isolate_cached_class_table_table_offset = 36;
 static constexpr dart::compiler::target::word AOT_Isolate_current_tag_offset =
     20;
 static constexpr dart::compiler::target::word AOT_Isolate_default_tag_offset =
@@ -6593,8 +6591,10 @@
     AOT_Isolate_cached_object_store_offset = 32;
 static constexpr dart::compiler::target::word
     AOT_IsolateGroup_shared_class_table_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_IsolateGroup_cached_class_table_table_offset = 16;
 static constexpr dart::compiler::target::word AOT_Isolate_single_step_offset =
-    44;
+    40;
 static constexpr dart::compiler::target::word AOT_Isolate_user_tag_offset = 16;
 static constexpr dart::compiler::target::word AOT_LinkedHashMap_data_offset =
     16;
@@ -7175,8 +7175,6 @@
 static constexpr dart::compiler::target::word AOT_ICData_owner_offset = 32;
 static constexpr dart::compiler::target::word AOT_ICData_state_bits_offset = 40;
 static constexpr dart::compiler::target::word AOT_Int32x4_value_offset = 8;
-static constexpr dart::compiler::target::word
-    AOT_Isolate_cached_class_table_table_offset = 72;
 static constexpr dart::compiler::target::word AOT_Isolate_current_tag_offset =
     40;
 static constexpr dart::compiler::target::word AOT_Isolate_default_tag_offset =
@@ -7187,8 +7185,10 @@
     AOT_Isolate_cached_object_store_offset = 64;
 static constexpr dart::compiler::target::word
     AOT_IsolateGroup_shared_class_table_offset = 16;
+static constexpr dart::compiler::target::word
+    AOT_IsolateGroup_cached_class_table_table_offset = 32;
 static constexpr dart::compiler::target::word AOT_Isolate_single_step_offset =
-    88;
+    80;
 static constexpr dart::compiler::target::word AOT_Isolate_user_tag_offset = 32;
 static constexpr dart::compiler::target::word AOT_LinkedHashMap_data_offset =
     32;
@@ -7775,8 +7775,6 @@
 static constexpr dart::compiler::target::word AOT_ICData_owner_offset = 32;
 static constexpr dart::compiler::target::word AOT_ICData_state_bits_offset = 40;
 static constexpr dart::compiler::target::word AOT_Int32x4_value_offset = 8;
-static constexpr dart::compiler::target::word
-    AOT_Isolate_cached_class_table_table_offset = 72;
 static constexpr dart::compiler::target::word AOT_Isolate_current_tag_offset =
     40;
 static constexpr dart::compiler::target::word AOT_Isolate_default_tag_offset =
@@ -7787,8 +7785,10 @@
     AOT_Isolate_cached_object_store_offset = 64;
 static constexpr dart::compiler::target::word
     AOT_IsolateGroup_shared_class_table_offset = 16;
+static constexpr dart::compiler::target::word
+    AOT_IsolateGroup_cached_class_table_table_offset = 32;
 static constexpr dart::compiler::target::word AOT_Isolate_single_step_offset =
-    88;
+    80;
 static constexpr dart::compiler::target::word AOT_Isolate_user_tag_offset = 32;
 static constexpr dart::compiler::target::word AOT_LinkedHashMap_data_offset =
     32;
@@ -8373,8 +8373,6 @@
 static constexpr dart::compiler::target::word AOT_ICData_owner_offset = 32;
 static constexpr dart::compiler::target::word AOT_ICData_state_bits_offset = 40;
 static constexpr dart::compiler::target::word AOT_Int32x4_value_offset = 8;
-static constexpr dart::compiler::target::word
-    AOT_Isolate_cached_class_table_table_offset = 72;
 static constexpr dart::compiler::target::word AOT_Isolate_current_tag_offset =
     40;
 static constexpr dart::compiler::target::word AOT_Isolate_default_tag_offset =
@@ -8385,8 +8383,10 @@
     AOT_Isolate_cached_object_store_offset = 64;
 static constexpr dart::compiler::target::word
     AOT_IsolateGroup_shared_class_table_offset = 16;
+static constexpr dart::compiler::target::word
+    AOT_IsolateGroup_cached_class_table_table_offset = 32;
 static constexpr dart::compiler::target::word AOT_Isolate_single_step_offset =
-    88;
+    80;
 static constexpr dart::compiler::target::word AOT_Isolate_user_tag_offset = 32;
 static constexpr dart::compiler::target::word AOT_LinkedHashMap_data_offset =
     32;
@@ -8970,8 +8970,6 @@
 static constexpr dart::compiler::target::word AOT_ICData_owner_offset = 32;
 static constexpr dart::compiler::target::word AOT_ICData_state_bits_offset = 40;
 static constexpr dart::compiler::target::word AOT_Int32x4_value_offset = 8;
-static constexpr dart::compiler::target::word
-    AOT_Isolate_cached_class_table_table_offset = 72;
 static constexpr dart::compiler::target::word AOT_Isolate_current_tag_offset =
     40;
 static constexpr dart::compiler::target::word AOT_Isolate_default_tag_offset =
@@ -8982,8 +8980,10 @@
     AOT_Isolate_cached_object_store_offset = 64;
 static constexpr dart::compiler::target::word
     AOT_IsolateGroup_shared_class_table_offset = 16;
+static constexpr dart::compiler::target::word
+    AOT_IsolateGroup_cached_class_table_table_offset = 32;
 static constexpr dart::compiler::target::word AOT_Isolate_single_step_offset =
-    88;
+    80;
 static constexpr dart::compiler::target::word AOT_Isolate_user_tag_offset = 32;
 static constexpr dart::compiler::target::word AOT_LinkedHashMap_data_offset =
     32;
@@ -9567,8 +9567,6 @@
 static constexpr dart::compiler::target::word AOT_ICData_owner_offset = 16;
 static constexpr dart::compiler::target::word AOT_ICData_state_bits_offset = 20;
 static constexpr dart::compiler::target::word AOT_Int32x4_value_offset = 8;
-static constexpr dart::compiler::target::word
-    AOT_Isolate_cached_class_table_table_offset = 36;
 static constexpr dart::compiler::target::word AOT_Isolate_current_tag_offset =
     20;
 static constexpr dart::compiler::target::word AOT_Isolate_default_tag_offset =
@@ -9579,6 +9577,8 @@
     AOT_Isolate_cached_object_store_offset = 32;
 static constexpr dart::compiler::target::word
     AOT_IsolateGroup_shared_class_table_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_IsolateGroup_cached_class_table_table_offset = 16;
 static constexpr dart::compiler::target::word AOT_Isolate_user_tag_offset = 16;
 static constexpr dart::compiler::target::word AOT_LinkedHashMap_data_offset =
     16;
@@ -10154,8 +10154,6 @@
 static constexpr dart::compiler::target::word AOT_ICData_owner_offset = 32;
 static constexpr dart::compiler::target::word AOT_ICData_state_bits_offset = 40;
 static constexpr dart::compiler::target::word AOT_Int32x4_value_offset = 8;
-static constexpr dart::compiler::target::word
-    AOT_Isolate_cached_class_table_table_offset = 72;
 static constexpr dart::compiler::target::word AOT_Isolate_current_tag_offset =
     40;
 static constexpr dart::compiler::target::word AOT_Isolate_default_tag_offset =
@@ -10166,6 +10164,8 @@
     AOT_Isolate_cached_object_store_offset = 64;
 static constexpr dart::compiler::target::word
     AOT_IsolateGroup_shared_class_table_offset = 16;
+static constexpr dart::compiler::target::word
+    AOT_IsolateGroup_cached_class_table_table_offset = 32;
 static constexpr dart::compiler::target::word AOT_Isolate_user_tag_offset = 32;
 static constexpr dart::compiler::target::word AOT_LinkedHashMap_data_offset =
     32;
@@ -10747,8 +10747,6 @@
 static constexpr dart::compiler::target::word AOT_ICData_owner_offset = 32;
 static constexpr dart::compiler::target::word AOT_ICData_state_bits_offset = 40;
 static constexpr dart::compiler::target::word AOT_Int32x4_value_offset = 8;
-static constexpr dart::compiler::target::word
-    AOT_Isolate_cached_class_table_table_offset = 72;
 static constexpr dart::compiler::target::word AOT_Isolate_current_tag_offset =
     40;
 static constexpr dart::compiler::target::word AOT_Isolate_default_tag_offset =
@@ -10759,6 +10757,8 @@
     AOT_Isolate_cached_object_store_offset = 64;
 static constexpr dart::compiler::target::word
     AOT_IsolateGroup_shared_class_table_offset = 16;
+static constexpr dart::compiler::target::word
+    AOT_IsolateGroup_cached_class_table_table_offset = 32;
 static constexpr dart::compiler::target::word AOT_Isolate_user_tag_offset = 32;
 static constexpr dart::compiler::target::word AOT_LinkedHashMap_data_offset =
     32;
@@ -11338,8 +11338,6 @@
 static constexpr dart::compiler::target::word AOT_ICData_owner_offset = 32;
 static constexpr dart::compiler::target::word AOT_ICData_state_bits_offset = 40;
 static constexpr dart::compiler::target::word AOT_Int32x4_value_offset = 8;
-static constexpr dart::compiler::target::word
-    AOT_Isolate_cached_class_table_table_offset = 72;
 static constexpr dart::compiler::target::word AOT_Isolate_current_tag_offset =
     40;
 static constexpr dart::compiler::target::word AOT_Isolate_default_tag_offset =
@@ -11350,6 +11348,8 @@
     AOT_Isolate_cached_object_store_offset = 64;
 static constexpr dart::compiler::target::word
     AOT_IsolateGroup_shared_class_table_offset = 16;
+static constexpr dart::compiler::target::word
+    AOT_IsolateGroup_cached_class_table_table_offset = 32;
 static constexpr dart::compiler::target::word AOT_Isolate_user_tag_offset = 32;
 static constexpr dart::compiler::target::word AOT_LinkedHashMap_data_offset =
     32;
@@ -11928,8 +11928,6 @@
 static constexpr dart::compiler::target::word AOT_ICData_owner_offset = 32;
 static constexpr dart::compiler::target::word AOT_ICData_state_bits_offset = 40;
 static constexpr dart::compiler::target::word AOT_Int32x4_value_offset = 8;
-static constexpr dart::compiler::target::word
-    AOT_Isolate_cached_class_table_table_offset = 72;
 static constexpr dart::compiler::target::word AOT_Isolate_current_tag_offset =
     40;
 static constexpr dart::compiler::target::word AOT_Isolate_default_tag_offset =
@@ -11940,6 +11938,8 @@
     AOT_Isolate_cached_object_store_offset = 64;
 static constexpr dart::compiler::target::word
     AOT_IsolateGroup_shared_class_table_offset = 16;
+static constexpr dart::compiler::target::word
+    AOT_IsolateGroup_cached_class_table_table_offset = 32;
 static constexpr dart::compiler::target::word AOT_Isolate_user_tag_offset = 32;
 static constexpr dart::compiler::target::word AOT_LinkedHashMap_data_offset =
     32;
diff --git a/runtime/vm/compiler/runtime_offsets_list.h b/runtime/vm/compiler/runtime_offsets_list.h
index 73a9fa5..3a0da0f 100644
--- a/runtime/vm/compiler/runtime_offsets_list.h
+++ b/runtime/vm/compiler/runtime_offsets_list.h
@@ -127,12 +127,12 @@
   FIELD(ICData, owner_offset)                                                  \
   FIELD(ICData, state_bits_offset)                                             \
   FIELD(Int32x4, value_offset)                                                 \
-  FIELD(Isolate, cached_class_table_table_offset)                              \
   FIELD(Isolate, current_tag_offset)                                           \
   FIELD(Isolate, default_tag_offset)                                           \
   FIELD(Isolate, ic_miss_code_offset)                                          \
   FIELD(Isolate, cached_object_store_offset)                                   \
   FIELD(IsolateGroup, shared_class_table_offset)                               \
+  FIELD(IsolateGroup, cached_class_table_table_offset)                         \
   NOT_IN_PRODUCT(FIELD(Isolate, single_step_offset))                           \
   FIELD(Isolate, user_tag_offset)                                              \
   FIELD(LinkedHashMap, data_offset)                                            \
diff --git a/runtime/vm/heap/heap.cc b/runtime/vm/heap/heap.cc
index 2422e51..734e76e 100644
--- a/runtime/vm/heap/heap.cc
+++ b/runtime/vm/heap/heap.cc
@@ -40,23 +40,6 @@
             false,
             "Explicitly disable heap verification.");
 
-// We ensure that the GC does not use the current isolate.
-class NoActiveIsolateScope {
- public:
-  NoActiveIsolateScope() : thread_(Thread::Current()) {
-    saved_isolate_ = thread_->isolate_;
-    thread_->isolate_ = nullptr;
-  }
-  ~NoActiveIsolateScope() {
-    ASSERT(thread_->isolate_ == nullptr);
-    thread_->isolate_ = saved_isolate_;
-  }
-
- private:
-  Thread* thread_;
-  Isolate* saved_isolate_;
-};
-
 Heap::Heap(IsolateGroup* isolate_group,
            bool is_vm_isolate,
            intptr_t max_new_gen_semi_words,
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 5b8ffb7..f781823 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -333,6 +333,8 @@
                            ObjectStore* object_store,
                            Dart_IsolateFlags api_flags)
     : shared_class_table_(new SharedClassTable()),
+      class_table_(new ClassTable(shared_class_table_.get())),
+      cached_class_table_table_(class_table_->table()),
       embedder_data_(embedder_data),
       thread_pool_(),
       isolates_lock_(new SafepointRwLock()),
@@ -349,7 +351,6 @@
       thread_registry_(new ThreadRegistry()),
       safepoint_handler_(new SafepointHandler(this)),
       object_store_(object_store),
-      class_table_(new ClassTable(shared_class_table_.get())),
       store_buffer_(new StoreBuffer()),
       heap_(nullptr),
       saved_unlinked_calls_(Array::null()),
@@ -890,17 +891,17 @@
   state->FreePersistentHandle(handle_);
 }
 
-void Isolate::RegisterClass(const Class& cls) {
+void IsolateGroup::RegisterClass(const Class& cls) {
 #if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
-  if (group()->IsReloading()) {
+  if (IsReloading()) {
     program_reload_context()->RegisterClass(cls);
     return;
   }
 #endif  // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
   if (cls.IsTopLevel()) {
-    group()->class_table()->RegisterTopLevel(cls);
+    class_table()->RegisterTopLevel(cls);
   } else {
-    group()->class_table()->Register(cls);
+    class_table()->Register(cls);
   }
 }
 
@@ -942,6 +943,18 @@
   }
 }
 
+void IsolateGroup::FreeStaticField(const Field& field) {
+#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
+  // This can only be called during hot-reload.
+  ASSERT(program_reload_context() != nullptr);
+#endif
+
+  const intptr_t field_id = field.field_id();
+  initial_field_table()->Free(field_id);
+  ForEachIsolate(
+      [&](Isolate* isolate) { isolate->field_table()->Free(field_id); });
+}
+
 void IsolateGroup::RehashConstants() {
   Thread* thread = Thread::Current();
   StackZone stack_zone(thread);
@@ -1700,7 +1713,6 @@
       isolate_object_store_(
           new IsolateObjectStore(isolate_group->object_store())),
       object_store_shared_ptr_(isolate_group->object_store_shared_ptr()),
-      class_table_(isolate_group->class_table_shared_ptr()),
 #if !defined(DART_PRECOMPILED_RUNTIME)
       native_callback_trampolines_(),
 #endif
@@ -1727,7 +1739,6 @@
       catch_entry_moves_cache_(),
       loaded_prefixes_set_storage_(nullptr) {
   cached_object_store_ = object_store_shared_ptr_.get();
-  cached_class_table_table_ = group()->class_table_->table();
   FlagsCopyFrom(api_flags);
   SetErrorsFatal(true);
   // TODO(asiva): A Thread is not available here, need to figure out
@@ -1996,10 +2007,24 @@
 }
 
 #if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
-bool Isolate::CanReload() const {
-  return !Isolate::IsSystemIsolate(this) && is_runnable() &&
-         !group()->IsReloading() && (group()->no_reload_scope_depth_ == 0) &&
-         IsolateCreationEnabled() &&
+bool IsolateGroup::CanReload() {
+  // TODO(dartbug.com/36097): As part of implementing hot-reload support for
+  // --enable-isolate-groups, we should make the reload implementation wait for
+  // any outstanding isolates to "check-in" (which should only be done after
+  // making them runnable) instead of refusing the reload.
+  bool all_runnable = true;
+  {
+    SafepointReadRwLocker ml(Thread::Current(), isolates_lock_.get());
+    for (Isolate* isolate : isolates_) {
+      if (!isolate->is_runnable()) {
+        all_runnable = false;
+        break;
+      }
+    }
+  }
+  return !IsolateGroup::IsSystemIsolateGroup(this) && all_runnable &&
+         !IsReloading() && (no_reload_scope_depth_ == 0) &&
+         Isolate::IsolateCreationEnabled() &&
          OSThread::Current()->HasStackHeadroom(64 * KB);
 }
 
@@ -2021,16 +2046,13 @@
   group_reload_context_ = group_reload_context;
 
   SetHasAttemptedReload(true);
-  ForEachIsolate([&](Isolate* isolate) {
-    isolate->program_reload_context_ =
-        new ProgramReloadContext(group_reload_context_, isolate);
-  });
+  program_reload_context_ =
+      new ProgramReloadContext(group_reload_context_, this);
   const bool success =
       group_reload_context_->Reload(force_reload, root_script_url, packages_url,
                                     /*kernel_buffer=*/nullptr,
                                     /*kernel_buffer_size=*/0);
   if (!dont_delete_reload_context) {
-    ForEachIsolate([&](Isolate* isolate) { isolate->DeleteReloadContext(); });
     DeleteReloadContext();
   }
   return success;
@@ -2054,29 +2076,22 @@
   group_reload_context_ = group_reload_context;
 
   SetHasAttemptedReload(true);
-  ForEachIsolate([&](Isolate* isolate) {
-    isolate->program_reload_context_ =
-        new ProgramReloadContext(group_reload_context_, isolate);
-  });
+  program_reload_context_ =
+      new ProgramReloadContext(group_reload_context_, this);
   const bool success = group_reload_context_->Reload(
       force_reload,
       /*root_script_url=*/nullptr,
       /*packages_url=*/nullptr, kernel_buffer, kernel_buffer_size);
   if (!dont_delete_reload_context) {
-    ForEachIsolate([&](Isolate* isolate) { isolate->DeleteReloadContext(); });
     DeleteReloadContext();
   }
   return success;
 }
 
 void IsolateGroup::DeleteReloadContext() {
-  SafepointOperationScope safepoint_scope(Thread::Current());
-  group_reload_context_.reset();
-}
-
-void Isolate::DeleteReloadContext() {
   // Another thread may be in the middle of GetClassForHeapWalkAt.
   SafepointOperationScope safepoint_scope(Thread::Current());
+  group_reload_context_.reset();
 
   delete program_reload_context_;
   program_reload_context_ = nullptr;
@@ -2627,14 +2642,6 @@
   if (debugger() != nullptr) {
     debugger()->VisitObjectPointers(visitor);
   }
-#if !defined(DART_PRECOMPILED_RUNTIME)
-  // Visit objects that are being used for isolate reload.
-  if (program_reload_context() != nullptr) {
-    program_reload_context()->VisitObjectPointers(visitor);
-    program_reload_context()->group_reload_context()->VisitObjectPointers(
-        visitor);
-  }
-#endif  // !defined(DART_PRECOMPILED_RUNTIME)
   if (ServiceIsolate::IsServiceIsolate(this)) {
     ServiceIsolate::VisitObjectPointers(visitor);
   }
@@ -2797,6 +2804,15 @@
   visitor->VisitPointer(reinterpret_cast<ObjectPtr*>(&boxed_field_list_));
 
   NOT_IN_PRECOMPILED(background_compiler()->VisitPointers(visitor));
+
+#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
+  // Visit objects that are being used for isolate reload.
+  if (program_reload_context() != nullptr) {
+    program_reload_context()->VisitObjectPointers(visitor);
+    program_reload_context()->group_reload_context()->VisitObjectPointers(
+        visitor);
+  }
+#endif  // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
 }
 
 void IsolateGroup::VisitStackPointers(ObjectPointerVisitor* visitor,
@@ -2860,7 +2876,7 @@
   ClassPtr raw_class = nullptr;
 #if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
   if (group()->IsReloading()) {
-    raw_class = program_reload_context()->GetClassForHeapWalkAt(cid);
+    raw_class = group()->program_reload_context()->GetClassForHeapWalkAt(cid);
   } else {
     raw_class = group()->class_table()->At(cid);
   }
@@ -3357,10 +3373,12 @@
   set_message_notify_callback(Isolate::WakePauseEventHandler);
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
-  const bool had_program_reload_context = program_reload_context() != nullptr;
+  const bool had_program_reload_context =
+      group()->program_reload_context() != nullptr;
   const int64_t start_time_micros = !had_program_reload_context
                                         ? 0
-                                        : program_reload_context()
+                                        : group()
+                                              ->program_reload_context()
                                               ->group_reload_context()
                                               ->start_time_micros();
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
@@ -3381,7 +3399,8 @@
     }
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
-    if (had_program_reload_context && (program_reload_context() == nullptr)) {
+    if (had_program_reload_context &&
+        (group()->program_reload_context() == nullptr)) {
       if (FLAG_trace_reload) {
         const int64_t reload_time_micros =
             OS::GetCurrentMonotonicMicros() - start_time_micros;
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index b73263d..809af6a 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -438,6 +438,18 @@
     return OFFSET_OF(IsolateGroup, shared_class_table_);
   }
 
+  ClassPtr* cached_class_table_table() {
+    return cached_class_table_table_.load();
+  }
+  void set_cached_class_table_table(ClassPtr* cached_class_table_table) {
+    cached_class_table_table_.store(cached_class_table_table);
+  }
+  static intptr_t cached_class_table_table_offset() {
+    COMPILE_ASSERT(sizeof(IsolateGroup::cached_class_table_table_) ==
+                   kWordSize);
+    return OFFSET_OF(IsolateGroup, cached_class_table_table_);
+  }
+
   void set_obfuscation_map(const char** map) { obfuscation_map_ = map; }
   const char** obfuscation_map() const { return obfuscation_map_; }
 
@@ -677,8 +689,14 @@
   IsolateGroupReloadContext* reload_context() {
     return group_reload_context_.get();
   }
+  ProgramReloadContext* program_reload_context() {
+    return program_reload_context_;
+  }
 
   void DeleteReloadContext();
+  bool CanReload();
+#else
+  bool CanReload() { return false; }
 #endif  // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
 
   bool IsReloading() const {
@@ -763,7 +781,9 @@
 
   MutatorThreadPool* thread_pool() { return thread_pool_.get(); }
 
+  void RegisterClass(const Class& cls);
   void RegisterStaticField(const Field& field, const Instance& initial_value);
+  void FreeStaticField(const Field& field);
 
   static bool AreIsolateGroupsEnabled() {
 #if defined(DART_PRECOMPILED_RUNTIME)
@@ -813,15 +833,14 @@
 
   void set_heap(std::unique_ptr<Heap> value);
 
-  const std::shared_ptr<ClassTable>& class_table_shared_ptr() const {
-    return class_table_;
-  }
   const std::shared_ptr<ObjectStore>& object_store_shared_ptr() const {
     return object_store_;
   }
 
   // Accessed from generated code.
   std::unique_ptr<SharedClassTable> shared_class_table_;
+  std::unique_ptr<ClassTable> class_table_;
+  AcqRelAtomic<ClassPtr*> cached_class_table_table_;
   // End accessed from generated code.
 
   const char** obfuscation_map_ = nullptr;
@@ -848,6 +867,7 @@
       0;  // we can only reload when this is 0.
   // Per-isolate-group copy of FLAG_reload_every.
   RelaxedAtomic<intptr_t> reload_every_n_stack_overflow_checks_;
+  ProgramReloadContext* program_reload_context_ = nullptr;
 #endif
 
 #define ISOLATE_METRIC_VARIABLE(type, variable, name, unit)                    \
@@ -876,7 +896,6 @@
   uint64_t id_ = 0;
 
   std::shared_ptr<ObjectStore> object_store_;
-  std::shared_ptr<ClassTable> class_table_;
   std::unique_ptr<StoreBuffer> store_buffer_;
   std::unique_ptr<Heap> heap_;
   std::unique_ptr<DispatchTable> dispatch_table_;
@@ -979,23 +998,12 @@
   bool IsScheduled() { return scheduled_mutator_thread() != nullptr; }
   Thread* scheduled_mutator_thread() const { return scheduled_mutator_thread_; }
 
-  // Register a newly introduced class.
-  void RegisterClass(const Class& cls);
-
   ThreadRegistry* thread_registry() const { return group()->thread_registry(); }
 
   SafepointHandler* safepoint_handler() const {
     return group()->safepoint_handler();
   }
 
-  ClassPtr* cached_class_table_table() { return cached_class_table_table_; }
-  void set_cached_class_table_table(ClassPtr* cached_class_table_table) {
-    cached_class_table_table_ = cached_class_table_table;
-  }
-  static intptr_t cached_class_table_table_offset() {
-    return OFFSET_OF(Isolate, cached_class_table_table_);
-  }
-
   void set_object_store(ObjectStore* object_store);
   static intptr_t cached_object_store_offset() {
     return OFFSET_OF(Isolate, cached_object_store_);
@@ -1263,20 +1271,6 @@
 
 #if !defined(PRODUCT)
   VMTagCounters* vm_tag_counters() { return &vm_tag_counters_; }
-
-#if !defined(DART_PRECOMPILED_RUNTIME)
-  ProgramReloadContext* program_reload_context() {
-    return program_reload_context_;
-  }
-
-  void DeleteReloadContext();
-
-  bool CanReload() const;
-#else
-  bool IsReloading() const { return false; }
-  bool HasAttemptedReload() const { return false; }
-  bool CanReload() const { return false; }
-#endif  // !defined(DART_PRECOMPILED_RUNTIME)
 #endif  // !defined(PRODUCT)
 
   bool IsPaused() const;
@@ -1545,8 +1539,6 @@
   CodePtr ic_miss_code_;
   // Cached value of object_store_shared_ptr_, here for generated code access
   ObjectStore* cached_object_store_ = nullptr;
-  // Cached value of class_table_->table_, here for generated code access
-  ClassPtr* cached_class_table_table_ = nullptr;
   FieldTable* field_table_ = nullptr;
   bool single_step_ = false;
   bool is_system_isolate_ = false;
@@ -1557,8 +1549,6 @@
   std::unique_ptr<IsolateObjectStore> isolate_object_store_;
   // shared in AOT(same pointer as on IsolateGroup), not shared in JIT
   std::shared_ptr<ObjectStore> object_store_shared_ptr_;
-  // shared in AOT(same pointer as on IsolateGroup), not shared in JIT
-  std::shared_ptr<ClassTable> class_table_;
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
   NativeCallbackTrampolines native_callback_trampolines_;
@@ -1617,7 +1607,6 @@
   ISOLATE_METRIC_LIST(ISOLATE_METRIC_VARIABLE);
 #undef ISOLATE_METRIC_VARIABLE
 
-  ProgramReloadContext* program_reload_context_ = nullptr;
   // Ring buffer of objects assigned an id.
   ObjectIdRing* object_id_ring_ = nullptr;
 #endif  // !defined(PRODUCT)
@@ -1713,7 +1702,6 @@
   friend class ServiceIsolate;
   friend class Thread;
   friend class Timeline;
-  friend class NoReloadScope;  // reload_block
   friend class IsolateGroup;   // reload_context_
 
   DISALLOW_COPY_AND_ASSIGN(Isolate);
@@ -1779,6 +1767,26 @@
   DISALLOW_COPY_AND_ASSIGN(EnterIsolateGroupScope);
 };
 
+// Ensure that isolate is not available for the duration of this scope.
+//
+// This can be used in code (e.g. GC, Kernel Loader) that should not operate on
+// an individual isolate.
+class NoActiveIsolateScope {
+ public:
+  NoActiveIsolateScope() : thread_(Thread::Current()) {
+    saved_isolate_ = thread_->isolate_;
+    thread_->isolate_ = nullptr;
+  }
+  ~NoActiveIsolateScope() {
+    ASSERT(thread_->isolate_ == nullptr);
+    thread_->isolate_ = saved_isolate_;
+  }
+
+ private:
+  Thread* thread_;
+  Isolate* saved_isolate_;
+};
+
 }  // namespace dart
 
 #endif  // RUNTIME_VM_ISOLATE_H_
diff --git a/runtime/vm/isolate_reload.cc b/runtime/vm/isolate_reload.cc
index 2a13446..c117abf 100644
--- a/runtime/vm/isolate_reload.cc
+++ b/runtime/vm/isolate_reload.cc
@@ -457,10 +457,10 @@
 
 ProgramReloadContext::ProgramReloadContext(
     std::shared_ptr<IsolateGroupReloadContext> group_reload_context,
-    Isolate* isolate)
+    IsolateGroup* isolate_group)
     : zone_(Thread::Current()->zone()),
       group_reload_context_(group_reload_context),
-      isolate_(isolate),
+      isolate_group_(isolate_group),
       saved_class_table_(nullptr),
       saved_tlc_class_table_(nullptr),
       old_classes_set_storage_(Array::null()),
@@ -562,12 +562,7 @@
 
   Thread* thread = Thread::Current();
 
-  // All isolates within an isolate group need to share one heap.
-  // TODO(dartbug.com/36097): Remove this assert once the shared heap CL has
-  // landed.
-  RELEASE_ASSERT(!IsolateGroup::AreIsolateGroupsEnabled());
   Heap* heap = IG->heap();
-
   num_old_libs_ =
       GrowableObjectArray::Handle(Z, IG->object_store()->libraries()).Length();
 
@@ -628,8 +623,8 @@
 
     modified_libs_ = new (Z) BitVector(Z, num_old_libs_);
     kernel::KernelLoader::FindModifiedLibraries(
-        kernel_program.get(), isolate_group_, modified_libs_, force_reload,
-        &skip_reload, p_num_received_classes, p_num_received_procedures);
+        kernel_program.get(), IG, modified_libs_, force_reload, &skip_reload,
+        p_num_received_classes, p_num_received_procedures);
     modified_libs_transitive_ = new (Z) BitVector(Z, num_old_libs_);
     BuildModifiedLibrariesClosure(modified_libs_);
 
@@ -682,12 +677,10 @@
   // assumptions from field guards or CHA or deferred library prefixes.
   // TODO(johnmccutchan): Deoptimizing dependent code here (before the reload)
   // is paranoid. This likely can be moved to the commit phase.
-  ForEachIsolate([&](Isolate* isolate) {
-    isolate->program_reload_context()->EnsuredUnoptimizedCodeForStack();
-    isolate->program_reload_context()->DeoptimizeDependentCode();
-    isolate->program_reload_context()
-        ->ReloadPhase1AllocateStorageMapsAndCheckpoint();
-  });
+  IG->program_reload_context()->EnsuredUnoptimizedCodeForStack();
+  IG->program_reload_context()->DeoptimizeDependentCode();
+  IG->program_reload_context()->ReloadPhase1AllocateStorageMapsAndCheckpoint();
+
   // Renumbering the libraries has invalidated this.
   modified_libs_ = nullptr;
   modified_libs_transitive_ = nullptr;
@@ -703,9 +696,7 @@
   {
     TIMELINE_SCOPE(CheckpointClasses);
     CheckpointSharedClassTable();
-    ForEachIsolate([&](Isolate* isolate) {
-      isolate->program_reload_context()->CheckpointClasses();
-    });
+    IG->program_reload_context()->CheckpointClasses();
   }
 
   if (FLAG_gc_during_reload) {
@@ -720,41 +711,24 @@
   //
   // If loading the hot-reload diff succeeded we'll finalize the loading, which
   // will either commit or reject the reload request.
-  const auto& results = Array::Handle(Z, Array::New(number_of_isolates));
-  intptr_t isolateIndex = 0;
-  intptr_t load_errors = 0;
+  const auto& result =
+      Object::Handle(Z, IG->program_reload_context()->ReloadPhase2LoadKernel(
+                            kernel_program.get(), root_lib_url_));
 
-  auto& tmp = Object::Handle(Z);
-  ForEachIsolate([&](Isolate* isolate) {
-    tmp = isolate->program_reload_context()->ReloadPhase2LoadKernel(
-        kernel_program.get(), root_lib_url_);
-    if (tmp.IsError()) {
-      results.SetAt(isolateIndex, tmp);
-      load_errors++;
-    }
-    isolateIndex++;
-  });
-
-  const auto& result = Object::Handle(results.At(0));
-
-  if (load_errors > 0) {
+  if (result.IsError()) {
     TIR_Print("---- LOAD FAILED, ABORTING RELOAD\n");
 
     const auto& error = Error::Cast(result);
     AddReasonForCancelling(new Aborted(Z, error));
 
     DiscardSavedClassTable(/*is_rollback=*/true);
-    ForEachIsolate([&](Isolate* isolate) {
-      isolate->program_reload_context()->ReloadPhase4Rollback();
-    });
+    IG->program_reload_context()->ReloadPhase4Rollback();
     CommonFinalizeTail(num_old_libs_);
   } else {
     ASSERT(!reload_skipped_ && !reload_finalized_);
     TIR_Print("---- LOAD SUCCEEDED\n");
 
-    ForEachIsolate([&](Isolate* isolate) {
-      isolate->program_reload_context()->ReloadPhase3FinalizeLoading();
-    });
+    IG->program_reload_context()->ReloadPhase3FinalizeLoading();
 
     if (FLAG_gc_during_reload) {
       // We use kLowMemory to force the GC to compact, which is more likely to
@@ -765,9 +739,7 @@
 
     if (!FLAG_reload_force_rollback && !HasReasonsForCancelling()) {
       TIR_Print("---- COMMITTING RELOAD\n");
-      ForEachIsolate([&](Isolate* isolate) {
-        isolate->program_reload_context()->ReloadPhase4CommitPrepare();
-      });
+      isolate_group_->program_reload_context()->ReloadPhase4CommitPrepare();
       bool discard_class_tables = true;
       if (HasInstanceMorphers()) {
         // Find all objects that need to be morphed (reallocated to a new size).
@@ -814,10 +786,8 @@
             // We accepted the hot-reload and morphed instances. So now we can
             // commit to the changed class table and deleted the saved one.
             DiscardSavedClassTable(/*is_rollback=*/false);
-            ForEachIsolate([&](Isolate* isolate) {
-              isolate->program_reload_context()->DiscardSavedClassTable(
-                  /*is_rollback=*/false);
-            });
+            IG->program_reload_context()->DiscardSavedClassTable(
+                /*is_rollback=*/false);
           }
           MorphInstancesPhase2Become(before, after);
 
@@ -833,22 +803,16 @@
       }
       if (discard_class_tables) {
         DiscardSavedClassTable(/*is_rollback=*/false);
-        ForEachIsolate([&](Isolate* isolate) {
-          isolate->program_reload_context()->DiscardSavedClassTable(
-              /*is_rollback=*/false);
-        });
+        IG->program_reload_context()->DiscardSavedClassTable(
+            /*is_rollback=*/false);
       }
-      ForEachIsolate([&](Isolate* isolate) {
-        isolate->program_reload_context()->ReloadPhase4CommitFinish();
-      });
+      isolate_group_->program_reload_context()->ReloadPhase4CommitFinish();
       TIR_Print("---- DONE COMMIT\n");
       isolate_group_->set_last_reload_timestamp(reload_timestamp_);
     } else {
       TIR_Print("---- ROLLING BACK");
       DiscardSavedClassTable(/*is_rollback=*/true);
-      ForEachIsolate([&](Isolate* isolate) {
-        isolate->program_reload_context()->ReloadPhase4Rollback();
-      });
+      isolate_group_->program_reload_context()->ReloadPhase4Rollback();
     }
 
     // ValidateReload mutates the direct subclass information and does
@@ -856,9 +820,7 @@
     // information from scratch.
     {
       SafepointWriteRwLocker ml(thread, IG->program_lock());
-      ForEachIsolate([&](Isolate* isolate) {
-        isolate->program_reload_context()->RebuildDirectSubclasses();
-      });
+      IG->program_reload_context()->RebuildDirectSubclasses();
     }
     const intptr_t final_library_count =
         GrowableObjectArray::Handle(Z, IG->object_store()->libraries())
@@ -879,7 +841,7 @@
   }
 
   bool success;
-  if (load_errors == 0 || HasReasonsForCancelling()) {
+  if (!result.IsError() || HasReasonsForCancelling()) {
     ReportSuccess();
     success = true;
   } else {
@@ -889,16 +851,14 @@
 
   // Re-queue any shutdown requests so they can inform each isolate's own thread
   // to shut down.
-  isolateIndex = 0;
-  ForEachIsolate([&](Isolate* isolate) {
-    tmp = results.At(isolateIndex);
-    if (tmp.IsUnwindError()) {
-      Isolate::KillIfExists(isolate, UnwindError::Cast(tmp).is_user_initiated()
+  if (result.IsUnwindError()) {
+    const auto& error = UnwindError::Cast(result);
+    ForEachIsolate([&](Isolate* isolate) {
+      Isolate::KillIfExists(isolate, error.is_user_initiated()
                                          ? Isolate::kKillMsg
                                          : Isolate::kInternalKillMsg);
-    }
-    isolateIndex++;
-  });
+    });
+  }
 
   return success;
 }
@@ -1104,7 +1064,7 @@
     if (lib.IsNull()) {
       lib = Library::LookupLibrary(thread, root_lib_url);
     }
-    isolate_->group()->object_store()->set_root_library(lib);
+    IG->object_store()->set_root_library(lib);
     return Object::null();
   } else {
     return thread->StealStickyError();
@@ -1210,23 +1170,26 @@
 
 void ProgramReloadContext::EnsuredUnoptimizedCodeForStack() {
   TIMELINE_SCOPE(EnsuredUnoptimizedCodeForStack);
-  StackFrameIterator it(ValidationPolicy::kDontValidateFrames,
-                        Thread::Current(),
-                        StackFrameIterator::kNoCrossThreadIteration);
 
-  Function& func = Function::Handle();
-  while (it.HasNextFrame()) {
-    StackFrame* frame = it.NextFrame();
-    if (frame->IsDartFrame()) {
-      func = frame->LookupDartFunction();
-      ASSERT(!func.IsNull());
-      // Force-optimized functions don't need unoptimized code because their
-      // optimized code cannot deopt.
-      if (!func.ForceOptimize()) {
-        func.EnsureHasCompiledUnoptimizedCode();
+  IG->ForEachIsolate([](Isolate* isolate) {
+    StackFrameIterator it(ValidationPolicy::kDontValidateFrames,
+                          isolate->mutator_thread(),
+                          StackFrameIterator::kAllowCrossThreadIteration);
+
+    Function& func = Function::Handle();
+    while (it.HasNextFrame()) {
+      StackFrame* frame = it.NextFrame();
+      if (frame->IsDartFrame()) {
+        func = frame->LookupDartFunction();
+        ASSERT(!func.IsNull());
+        // Force-optimized functions don't need unoptimized code because their
+        // optimized code cannot deopt.
+        if (!func.ForceOptimize()) {
+          func.EnsureHasCompiledUnoptimizedCode();
+        }
       }
     }
-  }
+  });
 }
 
 void ProgramReloadContext::DeoptimizeDependentCode() {
@@ -1934,7 +1897,7 @@
 }
 
 ObjectStore* ProgramReloadContext::object_store() {
-  return isolate_->group()->object_store();
+  return IG->object_store();
 }
 
 void ProgramReloadContext::ResetUnoptimizedICsOnStack() {
diff --git a/runtime/vm/isolate_reload.h b/runtime/vm/isolate_reload.h
index 74a32b9..b687e7f 100644
--- a/runtime/vm/isolate_reload.h
+++ b/runtime/vm/isolate_reload.h
@@ -305,7 +305,7 @@
  public:
   ProgramReloadContext(
       std::shared_ptr<IsolateGroupReloadContext> group_reload_context,
-      Isolate* isolate);
+      IsolateGroup* isolate_group);
   ~ProgramReloadContext();
 
   // All zone allocated objects must be allocated from this zone.
@@ -333,8 +333,7 @@
 
   void VisitObjectPointers(ObjectPointerVisitor* visitor);
 
-  Isolate* isolate() { return isolate_; }
-  IsolateGroup* isolate_group() { return isolate_->group(); }
+  IsolateGroup* isolate_group() { return isolate_group_; }
   ObjectStore* object_store();
 
   void EnsuredUnoptimizedCodeForStack();
@@ -382,7 +381,7 @@
   // The zone used for all reload related allocations.
   Zone* zone_;
   std::shared_ptr<IsolateGroupReloadContext> group_reload_context_;
-  Isolate* isolate_;
+  IsolateGroup* isolate_group_;
   intptr_t saved_num_cids_ = -1;
   intptr_t saved_num_tlc_cids_ = -1;
   std::atomic<ClassPtr*> saved_class_table_;
@@ -420,6 +419,7 @@
   ObjectPtr* to() { return reinterpret_cast<ObjectPtr*>(&saved_libraries_); }
 
   friend class Isolate;
+  friend class IsolateGroup;
   friend class Class;  // AddStaticFieldMapping, AddEnumBecomeMapping.
   friend class Library;
   friend class ObjectLocator;
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 740793b..33ac31c 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -4509,7 +4509,7 @@
   result.set_instance_size_in_words(0, 0);
 
   if (register_class) {
-    Isolate::Current()->RegisterClass(result);
+    IsolateGroup::Current()->RegisterClass(result);
   }
   return result.ptr();
 }
@@ -13231,7 +13231,7 @@
     // When reloading, we need to make sure we use the original private key
     // if this library previously existed.
     ProgramReloadContext* program_reload_context =
-        thread->isolate()->program_reload_context();
+        isolate_group->program_reload_context();
     const String& original_key =
         String::Handle(program_reload_context->FindLibraryPrivateKey(*this));
     if (!original_key.IsNull()) {
diff --git a/runtime/vm/object_reload.cc b/runtime/vm/object_reload.cc
index d4472ac..0a8c71f 100644
--- a/runtime/vm/object_reload.cc
+++ b/runtime/vm/object_reload.cc
@@ -219,13 +219,7 @@
           if (update_values && !field.is_const()) {
             // Make new field point to the old field value so that both
             // old and new code see and update same value.
-            //
-            // TODO(https://dartbug.com/36097): Once we look into enabling
-            // hot-reload with --enable-isolate-groups we have to do this
-            // for all isolates.
-            reload_context->isolate()->group()->initial_field_table()->Free(
-                field.field_id());
-            reload_context->isolate()->field_table()->Free(field.field_id());
+            reload_context->isolate_group()->FreeStaticField(field);
             field.set_field_id_unsafe(old_field.field_id());
           }
           reload_context->AddStaticFieldMapping(old_field, field);
diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc
index e70b4fe..849bf2f 100644
--- a/runtime/vm/runtime_entry.cc
+++ b/runtime/vm/runtime_entry.cc
@@ -2499,7 +2499,7 @@
         do_gc = true;
       }
       if ((isolate_reload_every > 0) && (count % isolate_reload_every) == 0) {
-        do_reload = isolate->CanReload();
+        do_reload = isolate->group()->CanReload();
       }
     }
   }
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index 4827248..ae26db2 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -3322,7 +3322,7 @@
     js->PrintError(kIsolateIsReloading, "This isolate is being reloaded.");
     return true;
   }
-  if (!isolate->CanReload()) {
+  if (!isolate_group->CanReload()) {
     js->PrintError(kFeatureDisabled,
                    "This isolate cannot reload sources right now.");
     return true;
diff --git a/runtime/vm/unit_test.cc b/runtime/vm/unit_test.cc
index 9213cfd..a4de697 100644
--- a/runtime/vm/unit_test.cc
+++ b/runtime/vm/unit_test.cc
@@ -529,14 +529,14 @@
 }
 
 Dart_Handle TestCase::TriggerReload(
-    std::function<bool(Isolate*, JSONStream*)> do_reload) {
+    std::function<bool(IsolateGroup*, JSONStream*)> do_reload) {
   Thread* thread = Thread::Current();
-  Isolate* isolate = thread->isolate();
+  IsolateGroup* isolate_group = thread->isolate_group();
   JSONStream js;
   bool success = false;
   {
     TransitionNativeToVM transition(thread);
-    success = do_reload(isolate, &js);
+    success = do_reload(isolate_group, &js);
     OS::PrintErr("RELOAD REPORT:\n%s\n", js.ToCString());
   }
 
@@ -547,41 +547,39 @@
 
   if (Dart_IsError(result)) {
     // Keep load error.
-  } else if (isolate->group()->reload_context()->reload_aborted()) {
+  } else if (isolate_group->reload_context()->reload_aborted()) {
     TransitionNativeToVM transition(thread);
-    result = Api::NewHandle(
-        thread,
-        isolate->program_reload_context()->group_reload_context()->error());
+    result = Api::NewHandle(thread, isolate_group->program_reload_context()
+                                        ->group_reload_context()
+                                        ->error());
   } else {
     result = Dart_RootLibrary();
   }
 
   TransitionNativeToVM transition(thread);
-  if (isolate->program_reload_context() != NULL) {
-    isolate->DeleteReloadContext();
-    isolate->group()->DeleteReloadContext();
+  if (isolate_group->program_reload_context() != NULL) {
+    isolate_group->DeleteReloadContext();
   }
 
   return result;
 }
 
 Dart_Handle TestCase::TriggerReload(const char* root_script_url) {
-  return TriggerReload([&](Isolate* isolate, JSONStream* js) {
-    return isolate->group()->ReloadSources(js,
-                                           /*force_reload=*/false,
-                                           root_script_url,
-                                           /*packages_url=*/nullptr,
-                                           /*dont_delete_reload_context=*/true);
+  return TriggerReload([&](IsolateGroup* isolate_group, JSONStream* js) {
+    return isolate_group->ReloadSources(js,
+                                        /*force_reload=*/false, root_script_url,
+                                        /*packages_url=*/nullptr,
+                                        /*dont_delete_reload_context=*/true);
   });
 }
 
 Dart_Handle TestCase::TriggerReload(const uint8_t* kernel_buffer,
                                     intptr_t kernel_buffer_size) {
-  return TriggerReload([&](Isolate* isolate, JSONStream* js) {
-    return isolate->group()->ReloadKernel(js,
-                                          /*force_reload=*/false, kernel_buffer,
-                                          kernel_buffer_size,
-                                          /*dont_delete_reload_context=*/true);
+  return TriggerReload([&](IsolateGroup* isolate_group, JSONStream* js) {
+    return isolate_group->ReloadKernel(js,
+                                       /*force_reload=*/false, kernel_buffer,
+                                       kernel_buffer_size,
+                                       /*dont_delete_reload_context=*/true);
   });
 }
 
diff --git a/runtime/vm/unit_test.h b/runtime/vm/unit_test.h
index 50d39eb..aa82e8d 100644
--- a/runtime/vm/unit_test.h
+++ b/runtime/vm/unit_test.h
@@ -401,7 +401,7 @@
 
  private:
   static Dart_Handle TriggerReload(
-      std::function<bool(Isolate*, JSONStream*)> do_reload);
+      std::function<bool(IsolateGroup*, JSONStream*)> do_reload);
 
   // |data_buffer| can either be snapshot data, or kernel binary data.
   // If |data_buffer| is snapshot data, then |len| should be zero as snapshot
diff --git a/tools/VERSION b/tools/VERSION
index 05f7464..f57edce 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 13
 PATCH 0
-PRERELEASE 29
+PRERELEASE 30
 PRERELEASE_PATCH 0
\ No newline at end of file