Version 2.18.0-127.0.dev

Merge commit 'a5e40e49169723c5e08fa696c4d83db6a20fcb70' into 'dev'
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index 8426836..0bd5019 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -372,9 +372,6 @@
     _newRefactoringManager();
   }
 
-  /// The analytics instance; note, this object can be `null`.
-  telemetry.Analytics? get analytics => options.analytics;
-
   /// The [Future] that completes when analysis is complete.
   Future<void> get onAnalysisComplete {
     if (isAnalysisComplete()) {
@@ -668,6 +665,8 @@
 
     pubApi.close();
 
+    // TODO(brianwilkerson) Remove the following 6 lines when the
+    //  analyticsManager is being correctly initialized.
     var analytics = options.analytics;
     if (analytics != null) {
       analytics.waitForLastPing(timeout: Duration(milliseconds: 200)).then((_) {
diff --git a/pkg/analysis_server/lib/src/analysis_server_abstract.dart b/pkg/analysis_server/lib/src/analysis_server_abstract.dart
index 1669d7b..45f1ca8 100644
--- a/pkg/analysis_server/lib/src/analysis_server_abstract.dart
+++ b/pkg/analysis_server/lib/src/analysis_server_abstract.dart
@@ -6,6 +6,8 @@
 import 'dart:io';
 
 import 'package:analysis_server/src/analysis_server.dart';
+import 'package:analysis_server/src/analytics/analytics_manager.dart';
+import 'package:analysis_server/src/analytics/noop_analytics_manager.dart';
 import 'package:analysis_server/src/collections.dart';
 import 'package:analysis_server/src/context_manager.dart';
 import 'package:analysis_server/src/domains/completion/available_suggestions.dart';
@@ -63,6 +65,9 @@
   /// The options of this server instance.
   AnalysisServerOptions options;
 
+  /// The object through which analytics are to be sent.
+  final AnalyticsManager analyticsManager;
+
   /// The builder for attachments that should be included into crash reports.
   final CrashReportingAttachmentsBuilder crashReportingAttachmentsBuilder;
 
@@ -159,7 +164,8 @@
     this.notificationManager, {
     this.requestStatistics,
     bool enableBazelWatcher = false,
-  })  : resourceProvider = OverlayResourceProvider(baseResourceProvider),
+  })  : analyticsManager = NoopAnalyticsManager(),
+        resourceProvider = OverlayResourceProvider(baseResourceProvider),
         pubApi = PubApi(instrumentationService, httpClient,
             Platform.environment['PUB_HOSTED_URL']) {
     // We can only spawn processes (eg. to run pub commands) when backed by
@@ -530,6 +536,7 @@
   @mustCallSuper
   void shutdown() {
     pubPackageService.shutdown();
+    analyticsManager.shutdown();
   }
 
   /// Return the path to the location of the byte store on disk, or `null` if
diff --git a/pkg/analysis_server/lib/src/analytics/analytics_manager.dart b/pkg/analysis_server/lib/src/analytics/analytics_manager.dart
new file mode 100644
index 0000000..125c1c2
--- /dev/null
+++ b/pkg/analysis_server/lib/src/analytics/analytics_manager.dart
@@ -0,0 +1,50 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/lsp_protocol/protocol.dart';
+import 'package:analysis_server/protocol/protocol.dart';
+import 'package:analysis_server/src/analytics/google_analytics_manager.dart';
+import 'package:telemetry/telemetry.dart';
+
+/// An interface for managing and reporting analytics.
+///
+/// Individual methods can either send an analytics event immediately or can
+/// collect and even consolidate information to be reported later. Clients are
+/// required to invoke the [shutdown] method before the server shuts down in
+/// order to send any cached data.
+abstract class AnalyticsManager {
+  /// Return an analytics manager that will report results using the given
+  /// [analytics].
+  factory AnalyticsManager.forAnalytics(Analytics analytics) =
+      GoogleAnalyticsManager;
+
+  /// Record that the given [response] was sent to the client.
+  void sentResponse({required Response response});
+
+  /// Record that the given [response] was sent to the client.
+  void sentResponseMessage({required ResponseMessage response});
+
+  /// The server is shutting down. Report any accumulated analytics data.
+  void shutdown();
+
+  /// Record that the server started working on the give [request] at the given
+  /// [startTime].
+  void startedRequest({required Request request, required DateTime startTime});
+
+  /// Record that the server started working on the give [request] at the given
+  /// [startTime].
+  void startedRequestMessage(
+      {required RequestMessage request, required DateTime startTime});
+
+  /// Record that the server was started at the given [time], that it was passed
+  /// the given command-line [arguments], that it was started by the client with
+  /// the given [clientId] and [clientVersion], and that it was invoked from an
+  /// SDK with the given [sdkVersion].
+  void startUp(
+      {required DateTime time,
+      required List<String> arguments,
+      required String clientId,
+      required String? clientVersion,
+      required String sdkVersion});
+}
diff --git a/pkg/analysis_server/lib/src/analytics/google_analytics_manager.dart b/pkg/analysis_server/lib/src/analytics/google_analytics_manager.dart
new file mode 100644
index 0000000..63ca84b
--- /dev/null
+++ b/pkg/analysis_server/lib/src/analytics/google_analytics_manager.dart
@@ -0,0 +1,202 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/lsp_protocol/protocol.dart';
+import 'package:analysis_server/protocol/protocol.dart';
+import 'package:analysis_server/src/analytics/analytics_manager.dart';
+import 'package:analysis_server/src/analytics/percentile_calculator.dart';
+import 'package:telemetry/telemetry.dart';
+
+/// An implementation of [AnalyticsManager] that's appropriate to use when
+/// analytics have been enabled.
+class GoogleAnalyticsManager implements AnalyticsManager {
+  /// The object used to send analytics.
+  final Analytics analytics;
+
+  /// Data about the current session, or `null` if the [startUp] method has not
+  /// been invoked.
+  _SessionData? sessionData;
+
+  /// A map from the id of a request to data about the request.
+  Map<String, _ActiveRequestData> activeRequests = {};
+
+  /// A map from the name of a request to data about all such requests that have
+  /// been responded to.
+  Map<String, _RequestData> completedRequests = {};
+
+  /// Initialize a newly created analytics manager to report to the [analytics]
+  /// service.
+  GoogleAnalyticsManager(this.analytics);
+
+  @override
+  void sentResponse({required Response response}) {
+    var sendTime = DateTime.now();
+    _recordResponseData(response.id, sendTime);
+  }
+
+  @override
+  void sentResponseMessage({required ResponseMessage response}) {
+    var sendTime = DateTime.now();
+    var id = response.id?.asString;
+    if (id == null) {
+      return;
+    }
+    _recordResponseData(id, sendTime);
+  }
+
+  @override
+  void shutdown() {
+    final sessionData = this.sessionData;
+    if (sessionData == null) {
+      return;
+    }
+    // Send session data.
+    var endTime = DateTime.now().millisecondsSinceEpoch;
+    var duration = endTime - sessionData.startTime.millisecondsSinceEpoch;
+    analytics.sendEvent('language_server', 'session', parameters: {
+      'flags': sessionData.commandLineArguments,
+      'clientId': sessionData.clientId,
+      'sdkVersion': sessionData.sdkVersion,
+      'duration': duration.toString(),
+      // TODO(brianwilkerson) Report a list of the names of the plugins that
+      //  were loaded, or possibly a map from plugin names to the number of
+      //  analysis roots in which the plugins were loaded.
+      'plugins': '',
+    });
+    // Send response data.
+    for (var data in completedRequests.values) {
+      analytics.sendEvent('language_server', 'request', parameters: {
+        'latency': data.latencyTimes.toAnalyticsString(),
+        'name': data.method,
+        'duration': data.responseTimes.toAnalyticsString(),
+        // TODO(brianwilkerson) Report the latencies for each of the plugins,
+        //  probably as a map from plugin name to latency information.
+        'plugins': '',
+      });
+    }
+    analytics.waitForLastPing(timeout: Duration(milliseconds: 200)).then((_) {
+      analytics.close();
+    });
+  }
+
+  @override
+  void startedRequest({required Request request, required DateTime startTime}) {
+    activeRequests[request.id] = _ActiveRequestData(
+        request.method, request.clientRequestTime, startTime);
+  }
+
+  @override
+  void startedRequestMessage(
+      {required RequestMessage request, required DateTime startTime}) {
+    activeRequests[request.id.asString] = _ActiveRequestData(
+        request.method.toString(), request.clientRequestTime, startTime);
+  }
+
+  @override
+  void startUp(
+      {required DateTime time,
+      required List<String> arguments,
+      required String clientId,
+      required String? clientVersion,
+      required String sdkVersion}) {
+    sessionData = _SessionData(
+        startTime: time,
+        commandLineArguments: arguments.join(' '),
+        clientId: clientId,
+        clientVersion: clientVersion ?? '',
+        sdkVersion: sdkVersion);
+  }
+
+  /// Record that the request with the given [id] was responded to at the given
+  /// [sendTime].
+  void _recordResponseData(String id, DateTime sendTime) {
+    var data = activeRequests.remove(id);
+    if (data == null) {
+      return;
+    }
+
+    var requestName = data.requestName;
+    var clientRequestTime = data.clientRequestTime;
+    var startTime = data.startTime.millisecondsSinceEpoch;
+
+    var requestData = completedRequests.putIfAbsent(
+        requestName, () => _RequestData(requestName));
+
+    if (clientRequestTime != null) {
+      var latencyTime = startTime - clientRequestTime;
+      requestData.latencyTimes.addValue(latencyTime);
+    }
+
+    var responseTime = sendTime.millisecondsSinceEpoch - startTime;
+    requestData.responseTimes.addValue(responseTime);
+  }
+}
+
+/// Data about a request that was received and is being handled.
+class _ActiveRequestData {
+  /// The name of the request that was received.
+  final String requestName;
+
+  /// The time at which the client sent the request.
+  final int? clientRequestTime;
+
+  /// The time at which the request was received.
+  final DateTime startTime;
+
+  /// Initialize a newly created data holder.
+  _ActiveRequestData(this.requestName, this.clientRequestTime, this.startTime);
+}
+
+/// Data about the requests that have been responded to that have the same name.
+class _RequestData {
+  /// The name of the requests.
+  final String method;
+
+  /// The percentile calculator for latency times. The _latency time_ is the
+  /// time from when the client sent the request until the time the server
+  /// started processing the request.
+  final PercentileCalculator latencyTimes = PercentileCalculator();
+
+  /// The percentile calculator for response times. The _response time_ is the
+  /// time from when the server started processing the request until the time
+  /// the response was sent.
+  final PercentileCalculator responseTimes = PercentileCalculator();
+
+  /// Initialize a newly create data holder for requests with the given
+  /// [method].
+  _RequestData(this.method);
+}
+
+/// Data about the current session.
+class _SessionData {
+  /// The time at which the current session started.
+  final DateTime startTime;
+
+  /// The command-line arguments passed to the server on startup.
+  final String commandLineArguments;
+
+  /// The name of the client that started the server.
+  final String clientId;
+
+  /// The version of the client that started the server, or an empty string if
+  /// no version information was provided.
+  final String clientVersion;
+
+  /// The version of the SDK from which the server was started.
+  final String sdkVersion;
+
+  /// Initialize a newly created data holder.
+  _SessionData(
+      {required this.startTime,
+      required this.commandLineArguments,
+      required this.clientId,
+      required this.clientVersion,
+      required this.sdkVersion});
+}
+
+extension on Either2<int, String> {
+  String get asString {
+    return map((value) => value.toString(), (value) => value);
+  }
+}
diff --git a/pkg/analysis_server/lib/src/analytics/noop_analytics_manager.dart b/pkg/analysis_server/lib/src/analytics/noop_analytics_manager.dart
new file mode 100644
index 0000000..36f46a5
--- /dev/null
+++ b/pkg/analysis_server/lib/src/analytics/noop_analytics_manager.dart
@@ -0,0 +1,36 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/lsp_protocol/protocol.dart';
+import 'package:analysis_server/protocol/protocol.dart';
+import 'package:analysis_server/src/analytics/analytics_manager.dart';
+
+/// An implementation of [AnalyticsManager] that's appropriate to use when
+/// analytics have not been enabled.
+class NoopAnalyticsManager implements AnalyticsManager {
+  @override
+  void sentResponse({required Response response}) {}
+
+  @override
+  void sentResponseMessage({required ResponseMessage response}) {}
+
+  @override
+  void shutdown() {}
+
+  @override
+  void startedRequest(
+      {required Request request, required DateTime startTime}) {}
+
+  @override
+  void startedRequestMessage(
+      {required RequestMessage request, required DateTime startTime}) {}
+
+  @override
+  void startUp(
+      {required DateTime time,
+      required List<String> arguments,
+      required String clientId,
+      required String? clientVersion,
+      required String sdkVersion}) {}
+}
diff --git a/pkg/analysis_server/lib/src/analytics/percentile_calculator.dart b/pkg/analysis_server/lib/src/analytics/percentile_calculator.dart
new file mode 100644
index 0000000..b1a313c
--- /dev/null
+++ b/pkg/analysis_server/lib/src/analytics/percentile_calculator.dart
@@ -0,0 +1,69 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// An object used to calculate percentile-based analytics.
+///
+/// See https://en.wikipedia.org/wiki/Percentile.
+class PercentileCalculator {
+  /// A map from values to the number of times the value has been recorded.
+  final Map<int, int> _counts = {};
+
+  /// The number of values in [_counts].
+  int _valueCount = 0;
+
+  /// Initialize a newly created percentile calculator.
+  PercentileCalculator();
+
+  /// Record that the given [value] has been seen.
+  void addValue(int value) {
+    _counts[value] = (_counts[value] ?? 0) + 1;
+    _valueCount++;
+  }
+
+  /// Remove all of the previously seen values.
+  void clear() {
+    _counts.clear();
+    _valueCount = 0;
+  }
+
+  /// Calculates the value at the given [percentile], which must be in the range
+  /// [0..100].
+  int percentile(int percentile) {
+    assert(percentile >= 0 && percentile <= 100);
+    if (_valueCount == 0) {
+      return 0;
+    }
+    var targetIndex = _valueCount * percentile / 100;
+    var values = _counts.keys.toList()..sort();
+    // The number of values represented by walking the counts.
+    var accumulation = 0;
+    for (var i = 0; i < values.length; i++) {
+      var value = values[i];
+      accumulation += _counts[value]!;
+      if (accumulation >= targetIndex) {
+        // We've now accounted for [targetIndex] values, which includes the
+        // median value.
+        return value;
+      }
+    }
+    throw StateError('');
+  }
+
+  /// Return a string that is suitable for sending to the analytics service.
+  String toAnalyticsString() {
+    var buffer = StringBuffer();
+    buffer.write('[');
+    for (var p = 5; p <= 100; p += 5) {
+      if (p > 5) {
+        buffer.write(', ');
+      }
+      buffer.write(percentile(p));
+    }
+    buffer.write(']');
+    return buffer.toString();
+  }
+
+  @override
+  String toString() => toAnalyticsString();
+}
diff --git a/pkg/analysis_server/lib/src/handler/legacy/analytics_enable.dart b/pkg/analysis_server/lib/src/handler/legacy/analytics_enable.dart
index 823b275..0c6b8b4 100644
--- a/pkg/analysis_server/lib/src/handler/legacy/analytics_enable.dart
+++ b/pkg/analysis_server/lib/src/handler/legacy/analytics_enable.dart
@@ -16,7 +16,7 @@
   @override
   Future<void> handle() async {
     var params = AnalyticsEnableParams.fromRequest(request);
-    final analytics = server.analytics;
+    final analytics = server.options.analytics;
     if (analytics != null) {
       analytics.enabled = params.value;
     }
diff --git a/pkg/analysis_server/lib/src/handler/legacy/analytics_is_enabled.dart b/pkg/analysis_server/lib/src/handler/legacy/analytics_is_enabled.dart
index 529d1d1..7410e2a 100644
--- a/pkg/analysis_server/lib/src/handler/legacy/analytics_is_enabled.dart
+++ b/pkg/analysis_server/lib/src/handler/legacy/analytics_is_enabled.dart
@@ -16,6 +16,7 @@
 
   @override
   Future<void> handle() async {
-    sendResult(AnalyticsIsEnabledResult(server.analytics?.enabled ?? false));
+    sendResult(
+        AnalyticsIsEnabledResult(server.options.analytics?.enabled ?? false));
   }
 }
diff --git a/pkg/analysis_server/lib/src/handler/legacy/analytics_send_event.dart b/pkg/analysis_server/lib/src/handler/legacy/analytics_send_event.dart
index fdb8f12..afb36ff 100644
--- a/pkg/analysis_server/lib/src/handler/legacy/analytics_send_event.dart
+++ b/pkg/analysis_server/lib/src/handler/legacy/analytics_send_event.dart
@@ -18,7 +18,7 @@
 
   @override
   Future<void> handle() async {
-    final analytics = server.analytics;
+    final analytics = server.options.analytics;
     if (analytics == null) {
       sendResult(AnalyticsSendEventResult());
       return;
diff --git a/pkg/analysis_server/lib/src/handler/legacy/analytics_send_timing.dart b/pkg/analysis_server/lib/src/handler/legacy/analytics_send_timing.dart
index a3266a0..bddc7d0 100644
--- a/pkg/analysis_server/lib/src/handler/legacy/analytics_send_timing.dart
+++ b/pkg/analysis_server/lib/src/handler/legacy/analytics_send_timing.dart
@@ -18,7 +18,7 @@
 
   @override
   Future<void> handle() async {
-    final analytics = server.analytics;
+    final analytics = server.options.analytics;
     if (analytics == null) {
       sendResult(AnalyticsSendTimingResult());
       return;
diff --git a/pkg/analysis_server/test/src/analytics/percentile_calculator_test.dart b/pkg/analysis_server/test/src/analytics/percentile_calculator_test.dart
new file mode 100644
index 0000000..a6a1047
--- /dev/null
+++ b/pkg/analysis_server/test/src/analytics/percentile_calculator_test.dart
@@ -0,0 +1,40 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/analytics/percentile_calculator.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(PercentileTest);
+  });
+}
+
+@reflectiveTest
+class PercentileTest {
+  var calculator = PercentileCalculator();
+
+  void test_clear() {
+    for (int i = 1; i <= 100; i++) {
+      calculator.addValue(i);
+    }
+    calculator.clear();
+    expect(calculator.toAnalyticsString(),
+        '[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]');
+  }
+
+  void test_toAnalyticsString_empty() {
+    expect(calculator.toAnalyticsString(),
+        '[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]');
+  }
+
+  void test_toAnalyticsString_evenDistribution() {
+    for (int i = 1; i <= 100; i++) {
+      calculator.addValue(i);
+    }
+    expect(calculator.toAnalyticsString(),
+        '[5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100]');
+  }
+}
diff --git a/pkg/analysis_server/test/src/analytics/test_all.dart b/pkg/analysis_server/test/src/analytics/test_all.dart
new file mode 100644
index 0000000..b969877
--- /dev/null
+++ b/pkg/analysis_server/test/src/analytics/test_all.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'percentile_calculator_test.dart' as percentile_calculator;
+
+void main() {
+  defineReflectiveSuite(() {
+    percentile_calculator.main();
+  });
+}
diff --git a/pkg/analysis_server/test/src/test_all.dart b/pkg/analysis_server/test/src/test_all.dart
index feab036..1b3b4b1 100644
--- a/pkg/analysis_server/test/src/test_all.dart
+++ b/pkg/analysis_server/test/src/test_all.dart
@@ -4,6 +4,7 @@
 
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import 'analytics/test_all.dart' as analytics;
 import 'cider/test_all.dart' as cider;
 import 'computer/test_all.dart' as computer;
 import 'domains/test_all.dart' as domains;
@@ -17,6 +18,7 @@
 
 void main() {
   defineReflectiveSuite(() {
+    analytics.main();
     cider.main();
     computer.main();
     domains.main();
diff --git a/pkg/front_end/lib/src/fasta/source/source_enum_builder.dart b/pkg/front_end/lib/src/fasta/source/source_enum_builder.dart
index f2812d0..43f0251 100644
--- a/pkg/front_end/lib/src/fasta/source/source_enum_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_enum_builder.dart
@@ -388,7 +388,8 @@
           AsyncMarker.Sync,
           procedureNameScheme,
           isExtensionMember: false,
-          isInstanceMember: true);
+          isInstanceMember: true,
+          isSynthetic: true);
       members["toString"] = toStringBuilder;
     }
     String className = name;
diff --git a/pkg/front_end/lib/src/fasta/source/source_procedure_builder.dart b/pkg/front_end/lib/src/fasta/source/source_procedure_builder.dart
index 1a7fe1f..2c412dd 100644
--- a/pkg/front_end/lib/src/fasta/source/source_procedure_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_procedure_builder.dart
@@ -76,7 +76,8 @@
       NameScheme nameScheme,
       {required bool isExtensionMember,
       required bool isInstanceMember,
-      String? nativeMethodName})
+      String? nativeMethodName,
+      bool isSynthetic: false})
       // ignore: unnecessary_null_comparison
       : assert(isExtensionMember != null),
         // ignore: unnecessary_null_comparison
@@ -90,7 +91,8 @@
         isExtensionInstanceMember ? ProcedureKind.Method : kind,
         new FunctionNode(null),
         fileUri: libraryBuilder.fileUri,
-        reference: procedureReference)
+        reference: procedureReference,
+        isSynthetic: isSynthetic)
       ..startFileOffset = startCharOffset
       ..fileOffset = charOffset
       ..fileEndOffset = charEndOffset
diff --git a/pkg/kernel/binary.md b/pkg/kernel/binary.md
index 4499a08..63f765a 100644
--- a/pkg/kernel/binary.md
+++ b/pkg/kernel/binary.md
@@ -437,7 +437,7 @@
   Byte stubKind; // Index into the ProcedureStubKind enum above.
   UInt flags (isStatic, isAbstract, isExternal, isConst,
               isRedirectingFactory, isExtensionMember,
-              isNonNullableByDefault);
+              isNonNullableByDefault, isSynthetic);
   Name name;
   List<Expression> annotations;
   MemberReference stubTarget; // May be NullReference.
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.h b/runtime/vm/compiler/frontend/kernel_translation_helper.h
index 046f874..65690a1 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.h
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.h
@@ -608,6 +608,7 @@
   bool IsAbstract() const { return (flags_ & kAbstract) != 0; }
   bool IsExternal() const { return (flags_ & kExternal) != 0; }
   bool IsConst() const { return (flags_ & kConst) != 0; }
+  bool IsSynthetic() const { return (flags_ & kSyntheticProcedure) != 0; }
   bool IsForwardingStub() const {
     return stub_kind_ == kAbstractForwardingStubKind ||
            stub_kind_ == kConcreteForwardingStubKind;
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index 2ccf215..65aea3a 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -154,6 +154,7 @@
 };
 static DartInitializationState init_state_;
 
+#if defined(DART_PRECOMPILER) || defined(DART_PRECOMPILED_RUNTIME)
 static void CheckOffsets() {
 #if !defined(IS_SIMARM_HOST64)
   // These offsets are embedded in precompiled instructions. We need the
@@ -243,9 +244,16 @@
 #undef CHECK_PAYLOAD_SIZEOF
 #endif  // !defined(IS_SIMARM_HOST64)
 }
+#endif  // defined(DART_PRECOMPILER) || defined(DART_PRECOMPILED_RUNTIME)
 
 char* Dart::DartInit(const Dart_InitializeParams* params) {
+#if defined(DART_PRECOMPILER) || defined(DART_PRECOMPILED_RUNTIME)
   CheckOffsets();
+#elif defined(ARCH_IS_64_BIT) != defined(TARGET_ARCH_IS_64_BIT)
+  return Utils::StrDup(
+      "JIT cannot simulate target architecture with different word size than "
+      "host");
+#endif
 
   if (!Flags::Initialized()) {
     return Utils::StrDup("VM initialization failed-VM Flags not initialized.");
diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc
index a9835fa..5cb7d4f 100644
--- a/runtime/vm/kernel_loader.cc
+++ b/runtime/vm/kernel_loader.cc
@@ -1977,6 +1977,7 @@
   bool is_abstract = procedure_helper.IsAbstract();
   bool is_external = procedure_helper.IsExternal();
   bool is_extension_member = procedure_helper.IsExtensionMember();
+  bool is_synthetic = procedure_helper.IsSynthetic();
   String& native_name = String::Handle(Z);
   bool scan_annotations_lazy;
   bool has_pragma_annotation;
@@ -2009,7 +2010,8 @@
   function.set_has_pragma(has_pragma_annotation);
   function.set_end_token_pos(procedure_helper.end_position_);
   function.set_is_synthetic(procedure_helper.IsNoSuchMethodForwarder() ||
-                            procedure_helper.IsMemberSignature());
+                            procedure_helper.IsMemberSignature() ||
+                            is_synthetic);
   function.set_is_visible(!is_invisible_function);
   if (register_function) {
     functions_.Add(&function);
diff --git a/runtime/vm/source_report_test.cc b/runtime/vm/source_report_test.cc
index f749b28..f445ff1 100644
--- a/runtime/vm/source_report_test.cc
+++ b/runtime/vm/source_report_test.cc
@@ -1073,6 +1073,56 @@
       buffer);
 }
 
+ISOLATE_UNIT_TEST_CASE(SourceReport_Coverage_IssueCov386_EnhancedEnums) {
+  // https://github.com/dart-lang/coverage/issues/386
+  // WARNING: This MUST be big enough for the serialised JSON string.
+  const int kBufferSize = 1024;
+  char buffer[kBufferSize];
+  const char* kScript =
+      "enum FoodType {\n"
+      "  candy();\n"
+      "  const FoodType();\n"
+      "}\n"
+      "void main() {\n"
+      "  final food = FoodType.candy;\n"
+      "}\n";
+
+  Library& lib = Library::Handle();
+  lib ^= ExecuteScript(kScript);
+  ASSERT(!lib.IsNull());
+  const Script& script =
+      Script::Handle(lib.LookupScript(String::Handle(String::New("test-lib"))));
+
+  SourceReport report(SourceReport::kCoverage, SourceReport::kForceCompile);
+  JSONStream js;
+  report.PrintJSON(&js, script);
+  const char* json_str = js.ToCString();
+  ASSERT(strlen(json_str) < kBufferSize);
+  ElideJSONSubstring("classes", json_str, buffer);
+  ElideJSONSubstring("libraries", buffer, buffer);
+  EXPECT_STREQ(
+      "{\"type\":\"SourceReport\",\"ranges\":["
+
+      // There are two ranges at the FoodType constructor. This one is missed,
+      // but the one below is hit, so it's ok. The point is that the synthetic
+      // toString method doesn't appear in this hitmap.
+      "{\"scriptIndex\":0,\"startPos\":29,\"endPos\":45,\"compiled\":true,"
+      "\"coverage\":{\"hits\":[],\"misses\":[29]}},"
+
+      // Main is hit.
+      "{\"scriptIndex\":0,\"startPos\":49,\"endPos\":94,\"compiled\":true,"
+      "\"coverage\":{\"hits\":[49],\"misses\":[]}},"
+
+      // FoodType constructor is hit.
+      "{\"scriptIndex\":0,\"compiled\":true,\"startPos\":29,\"endPos\":45,"
+      "\"coverage\":{\"hits\":[29],\"misses\":[]}}],"
+
+      // Only one script in the script table.
+      "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
+      "\"uri\":\"file:\\/\\/\\/test-lib\",\"_kind\":\"kernel\"}]}",
+      buffer);
+}
+
 ISOLATE_UNIT_TEST_CASE(SourceReport_Regress95008_RedirectingFactory) {
   // WARNING: This MUST be big enough for the serialised JSON string.
   const int kBufferSize = 1024;
diff --git a/tools/VERSION b/tools/VERSION
index 0b55526..c582ef0 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 18
 PATCH 0
-PRERELEASE 126
+PRERELEASE 127
 PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/utils/application_snapshot.gni b/utils/application_snapshot.gni
index 19cbb45..5679682 100644
--- a/utils/application_snapshot.gni
+++ b/utils/application_snapshot.gni
@@ -135,44 +135,51 @@
   }
 
   # Create a snapshot from kernel built above.
-  dart_action(target_name) {
-    if (defined(invoker.pool)) {
-      pool = invoker.pool
-    }
-    deps = extra_deps + [ ":${target_name}_dill" ]
-    depfile = "$output.d"
+  if (dart_snapshot_kind == "kernel") {
+    copy(target_name) {
+      deps = extra_deps + [ ":${target_name}_dill" ]
+      sources = [ "$target_gen_dir/$name.dart.dill" ]
+      outputs = [ output ]
 
-    script = "$target_gen_dir/$name.dart.dill"
-
-    inputs = extra_inputs
-
-    outputs = [ output ]
-
-    # Explicitly set DFE so Dart doesn't implicitly depend on the kernel service
-    # snapshot (creating a circular dep. for kernel-service_snapshot).
-    dfe = "NEVER_LOADED"
-
-    abs_depfile = rebase_path(depfile)
-    abs_output = rebase_path(output)
-    rel_output = rebase_path(output, root_build_dir)
-
-    vm_args = [
-                "--deterministic",
-                "--packages=$dot_packages",
-                "--snapshot=$abs_output",
-                "--snapshot-depfile=$abs_depfile",
-                "--depfile-output-filename=$rel_output",
-              ] + snapshot_vm_args
-
-    if (dart_snapshot_kind == "kernel") {
-      vm_args += [ "--snapshot-kind=kernel" ]
+      assert(snapshot_vm_args != "", "Ignoring unused argument")
       assert(training_args != "", "Ignoring unused argument")
-      args = []
-    } else if (dart_snapshot_kind == "app-jit") {
-      vm_args += [ "--snapshot-kind=app-jit" ]
-      args = training_args
-    } else {
-      assert(false, "Bad dart_snapshot_kind: $dart_snapshot_kind")
+    }
+  } else {
+    dart_action(target_name) {
+      if (defined(invoker.pool)) {
+        pool = invoker.pool
+      }
+      deps = extra_deps + [ ":${target_name}_dill" ]
+      depfile = "$output.d"
+
+      script = "$target_gen_dir/$name.dart.dill"
+
+      inputs = extra_inputs
+
+      outputs = [ output ]
+
+      # Explicitly set DFE so Dart doesn't implicitly depend on the kernel service
+      # snapshot (creating a circular dep. for kernel-service_snapshot).
+      dfe = "NEVER_LOADED"
+
+      abs_depfile = rebase_path(depfile)
+      abs_output = rebase_path(output)
+      rel_output = rebase_path(output, root_build_dir)
+
+      vm_args = [
+                  "--deterministic",
+                  "--packages=$dot_packages",
+                  "--snapshot=$abs_output",
+                  "--snapshot-depfile=$abs_depfile",
+                  "--depfile-output-filename=$rel_output",
+                ] + snapshot_vm_args
+
+      if (dart_snapshot_kind == "app-jit") {
+        vm_args += [ "--snapshot-kind=app-jit" ]
+        args = training_args
+      } else {
+        assert(false, "Bad dart_snapshot_kind: $dart_snapshot_kind")
+      }
     }
   }
 }