Version 3.5.0-90.0.dev

Merge 7fc712791c7028c54c8ba15bef3cb5ee5b075f9d into dev
diff --git a/pkg/frontend_server/lib/frontend_server.dart b/pkg/frontend_server/lib/frontend_server.dart
index 2989a53..0fa5f98 100644
--- a/pkg/frontend_server/lib/frontend_server.dart
+++ b/pkg/frontend_server/lib/frontend_server.dart
@@ -23,6 +23,8 @@
         ExpressionCompiler,
         parseModuleFormat,
         ProgramCompiler;
+import 'package:front_end/src/api_prototype/macros.dart' as macros
+    show isMacroLibraryUri;
 import 'package:front_end/src/api_unstable/ddc.dart' as ddc
     show IncrementalCompiler;
 import 'package:front_end/src/api_unstable/vm.dart';
@@ -643,7 +645,9 @@
         nativeAssetsLibrary: _nativeAssetsLibrary,
         classHierarchy: compilerResult.classHierarchy,
         coreTypes: compilerResult.coreTypes,
-        compiledSources: component.uriToSource.keys,
+        // TODO(https://dartbug.com/55246): track macro deps when available.
+        compiledSources: component.uriToSource.keys
+            .where((uri) => !macros.isMacroLibraryUri(uri)),
       );
 
       incrementalSerializer = _generator.incrementalSerializer;
@@ -695,6 +699,7 @@
           .writeln('$boundaryKey $_kernelBinaryFilename ${errors.length}');
       final String? depfile = options['depfile'];
       if (depfile != null) {
+        // TODO(https://dartbug.com/55246): track macro deps when available.
         await writeDepfile(compilerOptions.fileSystem, compiledSources,
             _kernelBinaryFilename, depfile);
       }
diff --git a/runtime/lib/object.cc b/runtime/lib/object.cc
index 8d7c48f..eeb3f64 100644
--- a/runtime/lib/object.cc
+++ b/runtime/lib/object.cc
@@ -329,20 +329,28 @@
   return Object::null();
 }
 
-DEFINE_NATIVE_ENTRY(Internal_randomInstructionsOffsetInsideAllocateObjectStub,
-                    0,
-                    0) {
+DEFINE_NATIVE_ENTRY(Internal_allocateObjectInstructionsStart, 0, 0) {
   auto& stub = Code::Handle(
       zone, isolate->group()->object_store()->allocate_object_stub());
-  const uword entry = stub.EntryPoint();
-  const uword random_offset = isolate->random()->NextUInt32() % stub.Size();
-  // We return the offset into the isolate instructions instead of the full
-  // address because that fits into small Smis on 32-bit architectures or
-  // compressed pointer builds.
+  ASSERT(!stub.IsUnknownDartCode());
+  // We return the start offset in the isolate instructions instead of the
+  // full address because that fits into small Smis on 32-bit architectures
+  // or compressed pointer builds.
   const uword instructions_start =
       reinterpret_cast<uword>(isolate->source()->snapshot_instructions);
-  ASSERT(entry >= instructions_start);
-  return Smi::New((entry - instructions_start) + random_offset);
+  return Smi::New(stub.PayloadStart() - instructions_start);
+}
+
+DEFINE_NATIVE_ENTRY(Internal_allocateObjectInstructionsEnd, 0, 0) {
+  auto& stub = Code::Handle(
+      zone, isolate->group()->object_store()->allocate_object_stub());
+  ASSERT(!stub.IsUnknownDartCode());
+  // We return the end offset in the isolate instructions instead of the
+  // full address because that fits into small Smis on 32-bit architectures
+  // or compressed pointer builds.
+  const uword instructions_start =
+      reinterpret_cast<uword>(isolate->source()->snapshot_instructions);
+  return Smi::New((stub.PayloadStart() - instructions_start) + stub.Size());
 }
 
 static bool ExtractInterfaceTypeArgs(Zone* zone,
diff --git a/runtime/tests/vm/dart/use_dwarf_stack_traces_flag_program.dart b/runtime/tests/vm/dart/use_dwarf_stack_traces_flag_program.dart
index cb53b42..eac4500 100644
--- a/runtime/tests/vm/dart/use_dwarf_stack_traces_flag_program.dart
+++ b/runtime/tests/vm/dart/use_dwarf_stack_traces_flag_program.dart
@@ -15,7 +15,7 @@
 foo(c) => bar(c);
 
 main() {
-  print(
-      VMInternalsForTesting.randomInstructionsOffsetInsideAllocateObjectStub());
+  print(VMInternalsForTesting.allocateObjectInstructionsStart());
+  print(VMInternalsForTesting.allocateObjectInstructionsEnd());
   var a = foo(new C());
 }
diff --git a/runtime/tests/vm/dart/use_dwarf_stack_traces_flag_test.dart b/runtime/tests/vm/dart/use_dwarf_stack_traces_flag_test.dart
index 54a6356..b1dab8b 100644
--- a/runtime/tests/vm/dart/use_dwarf_stack_traces_flag_test.dart
+++ b/runtime/tests/vm/dart/use_dwarf_stack_traces_flag_test.dart
@@ -223,9 +223,10 @@
 
 class DwarfTestOutput {
   final List<String> trace;
-  final int allocateObjectInstructionsOffset;
+  final int allocateObjectStart;
+  final int allocateObjectEnd;
 
-  DwarfTestOutput(this.trace, this.allocateObjectInstructionsOffset);
+  DwarfTestOutput(this.trace, this.allocateObjectStart, this.allocateObjectEnd);
 }
 
 Future<void> compareTraces(List<String> nonDwarfTrace, DwarfTestOutput output1,
@@ -312,9 +313,9 @@
   Expect.isNotNull(header.compressedPointers);
 }
 
-Future<void> checkRootUnitAssumptions(
+void checkRootUnitAssumptions(
     DwarfTestOutput output1, DwarfTestOutput output2, Dwarf rootDwarf,
-    {required PCOffset sampleOffset, bool matchingBuildIds = true}) async {
+    {required PCOffset sampleOffset, bool matchingBuildIds = true}) {
   // We run the test program on the same host OS as the test, so any
   // PCOffset from the trace should have this information.
   Expect.isNotNull(sampleOffset.os);
@@ -354,40 +355,50 @@
     Expect.stringEquals(dwarfBuildId, buildId2);
   }
 
-  final allocateObjectPCOffset1 = PCOffset(
-      output1.allocateObjectInstructionsOffset, InstructionsSection.isolate);
-  print('Offset of first stub address is $allocateObjectPCOffset1');
-  final allocateObjectPCOffset2 = PCOffset(
-      output2.allocateObjectInstructionsOffset, InstructionsSection.isolate);
-  print('Offset of second stub address is $allocateObjectPCOffset2');
+  final allocateObjectStart = output1.allocateObjectStart;
+  final allocateObjectEnd = output1.allocateObjectEnd;
+  Expect.equals(allocateObjectStart, output2.allocateObjectStart);
+  Expect.equals(allocateObjectEnd, output2.allocateObjectEnd);
 
-  final allocateObjectCallInfo1 = rootDwarf.callInfoForPCOffset(
-      allocateObjectPCOffset1,
-      includeInternalFrames: true);
-  print('Call info for first stub address is $allocateObjectCallInfo1');
-  final allocateObjectCallInfo2 = rootDwarf.callInfoForPCOffset(
-      allocateObjectPCOffset2,
-      includeInternalFrames: true);
-  print('Call info for second stub address is $allocateObjectCallInfo2');
-
-  Expect.isNotNull(allocateObjectCallInfo1);
-  Expect.isNotNull(allocateObjectCallInfo2);
-  Expect.equals(allocateObjectCallInfo1!.length, 1);
-  Expect.equals(allocateObjectCallInfo2!.length, 1);
-  Expect.isTrue(
-      allocateObjectCallInfo1.first is StubCallInfo, 'is not a StubCall');
-  Expect.isTrue(
-      allocateObjectCallInfo2.first is StubCallInfo, 'is not a StubCall');
-  final stubCall1 = allocateObjectCallInfo1.first as StubCallInfo;
-  final stubCall2 = allocateObjectCallInfo2.first as StubCallInfo;
-  Expect.equals(stubCall1.name, stubCall2.name);
-  Expect.contains('AllocateObject', stubCall1.name);
-  Expect.contains('AllocateObject', stubCall2.name);
+  checkAllocateObjectOffset(rootDwarf, allocateObjectStart);
+  // The end of the bare instructions payload may be padded up to word size,
+  // so check the maximum possible word size (64 bits) before the end.
+  checkAllocateObjectOffset(rootDwarf, allocateObjectEnd - 8);
+  // The end should be either in a different stub or not a stub altogether.
+  checkAllocateObjectOffset(rootDwarf, allocateObjectEnd, expectedValue: false);
+  // The byte before the start should also be in either a different stub or
+  // not in a stub altogether.
+  checkAllocateObjectOffset(rootDwarf, allocateObjectStart - 1,
+      expectedValue: false);
+  // Check the midpoint of the stub, as the stub should be large enough that the
+  // midpoint won't be in any possible padding.
+  Expect.isTrue(allocateObjectEnd - allocateObjectStart >= 16,
+      'midpoint of stub may be in bare payload padding');
+  checkAllocateObjectOffset(
+      rootDwarf, (allocateObjectStart + allocateObjectEnd) ~/ 2);
 
   print("Successfully matched AllocateObject stub addresses");
   print("");
 }
 
+void checkAllocateObjectOffset(Dwarf dwarf, int offset,
+    {bool expectedValue = true}) {
+  final pcOffset = PCOffset(offset, InstructionsSection.isolate);
+  print('Offset of tested stub address is $pcOffset');
+  final callInfo =
+      dwarf.callInfoForPCOffset(pcOffset, includeInternalFrames: true);
+  print('Call info for tested stub address is $callInfo');
+  final got = callInfo != null &&
+      callInfo.length == 1 &&
+      callInfo.single is StubCallInfo &&
+      (callInfo.single as StubCallInfo).name.endsWith('AllocateObjectStub');
+  Expect.equals(
+      expectedValue,
+      got,
+      'address is ${expectedValue ? 'not within' : 'within'} '
+      'the AllocateObject stub');
+}
+
 void checkTranslatedTrace(List<String> nonDwarfTrace, List<String> dwarfTrace) {
   final translatedStackFrames = onlySymbolicFrameLines(dwarfTrace);
   final originalStackFrames = onlySymbolicFrameLines(nonDwarfTrace);
@@ -425,8 +436,13 @@
   Expect.isTrue(result.stdout.isNotEmpty);
   Expect.isTrue(result.stderr.isNotEmpty);
 
+  final stdoutLines = LineSplitter.split(result.stdout).toList();
+  Expect.isTrue(stdoutLines.length >= 2);
+  final start = int.parse(stdoutLines[0]);
+  final end = int.parse(stdoutLines[1]);
+
   return DwarfTestOutput(
-      LineSplitter.split(result.stderr).toList(), int.parse(result.stdout));
+      LineSplitter.split(result.stderr).toList(), start, end);
 }
 
 final _buildIdRE = RegExp(r"build_id: '([a-f\d]+)'");
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index 1a8ba66..9ab26b1 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -281,7 +281,8 @@
   V(Internal_writeIntoOneByteString, 3)                                        \
   V(Internal_writeIntoTwoByteString, 3)                                        \
   V(Internal_deoptimizeFunctionsOnStack, 0)                                    \
-  V(Internal_randomInstructionsOffsetInsideAllocateObjectStub, 0)              \
+  V(Internal_allocateObjectInstructionsStart, 0)                               \
+  V(Internal_allocateObjectInstructionsEnd, 0)                                 \
   V(InvocationMirror_unpackTypeArguments, 2)                                   \
   V(NoSuchMethodError_existingMethodSignature, 3)                              \
   V(Uri_isWindowsPlatform, 0)                                                  \
diff --git a/sdk/lib/_internal/vm/lib/internal_patch.dart b/sdk/lib/_internal/vm/lib/internal_patch.dart
index 6c66c42..de34c9c 100644
--- a/sdk/lib/_internal/vm/lib/internal_patch.dart
+++ b/sdk/lib/_internal/vm/lib/internal_patch.dart
@@ -165,11 +165,16 @@
   external static void deoptimizeFunctionsOnStack();
 
   // Used to verify that PC addresses in stubs can be named using DWARF info
-  // by returning an offset into the isolate instructions that should correspond
+  // by returning the start offset into the isolate instructions that
+  // corresponds to a known stub.
+  @pragma("vm:external-name", "Internal_allocateObjectInstructionsStart")
+  external static int allocateObjectInstructionsStart();
+
+  // Used to verify that PC addresses in stubs can be named using DWARF info
+  // by returning the end offset into the isolate instructions that corresponds
   // to a known stub.
-  @pragma("vm:external-name",
-      "Internal_randomInstructionsOffsetInsideAllocateObjectStub")
-  external static int randomInstructionsOffsetInsideAllocateObjectStub();
+  @pragma("vm:external-name", "Internal_allocateObjectInstructionsEnd")
+  external static int allocateObjectInstructionsEnd();
 }
 
 @patch
diff --git a/tools/VERSION b/tools/VERSION
index e811ec5..795a815 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 3
 MINOR 5
 PATCH 0
-PRERELEASE 89
+PRERELEASE 90
 PRERELEASE_PATCH 0