Version 2.15.0-217.0.dev

Merge commit '238a72a3213eb5859141d7b34eb02309deab173c' into 'dev'
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b868d35..2d4be95 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -293,6 +293,8 @@
 - **Breaking Change** [#46875](https://github.com/dart-lang/sdk/issues/46875):
   The `SecurityContext` class in `dart:io` has been updated to set the minimum
   TLS protocol version to TLS1_2_VERSION (1.2) instead of TLS1_VERSION.
+- Add `RawSocket.sendMessage`, `RawSocket.receiveMessage` that allow passing of
+  file handle references via Unix domain sockets.
 
 ### Tools
 
diff --git a/DEPS b/DEPS
index 54d174b..6c75f52 100644
--- a/DEPS
+++ b/DEPS
@@ -64,8 +64,8 @@
   # The list of revisions for these tools comes from Fuchsia, here:
   # https://fuchsia.googlesource.com/integration/+/HEAD/prebuilts
   # If there are problems with the toolchain, contact fuchsia-toolchain@.
-  "clang_revision": "7c4e9a68264ffeef6178865be76c45c4fb6390af",
-  "gn_revision": "39a87c0b36310bdf06b692c098f199a0d97fc810",
+  "clang_revision": "f37e8b0b831e61d3b6033829fff05d6d193ab735",
+  "gn_revision": "693f9fb87e4febdd4299db9f73d8d2c958e63148",
 
   # Scripts that make 'git cl format' work.
   "clang_format_scripts_rev": "c09c8deeac31f05bd801995c475e7c8070f9ecda",
diff --git a/pkg/analysis_server/tool/spec/from_html.dart b/pkg/analysis_server/tool/spec/from_html.dart
index bf64d22..d3a1ce7 100644
--- a/pkg/analysis_server/tool/spec/from_html.dart
+++ b/pkg/analysis_server/tool/spec/from_html.dart
@@ -529,7 +529,7 @@
       throw Exception('$context: name not specified');
     }
 
-    context = '$context.$name}';
+    context = '$context.$name';
     checkAttributes(html, ['name'], context,
         optionalAttributes: [
           'optional',
diff --git a/pkg/analysis_server/tool/spec/to_html.dart b/pkg/analysis_server/tool/spec/to_html.dart
index 0bcc45e..6138199 100644
--- a/pkg/analysis_server/tool/spec/to_html.dart
+++ b/pkg/analysis_server/tool/spec/to_html.dart
@@ -754,6 +754,7 @@
     writeln('{');
     indent(() {
       for (var field in typeObject.fields) {
+        if (field.experimental) continue;
         write('"');
         if (fieldsToBold.contains(field.name)) {
           b(() {
diff --git a/pkg/analyzer/lib/src/summary2/bundle_reader.dart b/pkg/analyzer/lib/src/summary2/bundle_reader.dart
index bd9248b..056696d 100644
--- a/pkg/analyzer/lib/src/summary2/bundle_reader.dart
+++ b/pkg/analyzer/lib/src/summary2/bundle_reader.dart
@@ -63,7 +63,6 @@
     });
 
     for (var libraryHeader in libraryHeaderList) {
-      _reader.offset = libraryHeader.offset;
       var uriStr = libraryHeader.uriStr;
       var reference = elementFactory.rootReference.getChild(uriStr);
       libraryMap[uriStr] = LibraryReader._(
@@ -73,7 +72,7 @@
         baseResolutionOffset: baseResolutionOffset,
         referenceReader: referenceReader,
         reference: reference,
-        offset: _reader.offset,
+        offset: libraryHeader.offset,
         classMembersLengths: libraryHeader.classMembersLengths,
       );
     }
diff --git a/pkg/analyzer/lib/src/summary2/data_reader.dart b/pkg/analyzer/lib/src/summary2/data_reader.dart
index f9986ed..ff6e1b8 100644
--- a/pkg/analyzer/lib/src/summary2/data_reader.dart
+++ b/pkg/analyzer/lib/src/summary2/data_reader.dart
@@ -73,7 +73,8 @@
   }
 
   String readStringReference() {
-    return _stringTable[readUInt30()];
+    var index = readUInt30();
+    return stringOfIndex(index);
   }
 
   List<String> readStringReferenceList() {
diff --git a/pkg/analyzer_plugin/tool/spec/from_html.dart b/pkg/analyzer_plugin/tool/spec/from_html.dart
index cd144a9..53dc875 100644
--- a/pkg/analyzer_plugin/tool/spec/from_html.dart
+++ b/pkg/analyzer_plugin/tool/spec/from_html.dart
@@ -478,11 +478,22 @@
   /// Child elements can occur in any order.
   TypeObjectField typeObjectFieldFromHtml(dom.Element html, String context) {
     checkName(html, 'field', context);
+
     var name = html.attributes['name'];
-    context = '$context.${name ?? 'field'}';
+    if (name == null) {
+      throw Exception('$context: name not specified');
+    }
+
+    context = '$context.$name';
     checkAttributes(html, ['name'], context,
-        optionalAttributes: ['optional', 'value', 'deprecated']);
+        optionalAttributes: [
+          'optional',
+          'value',
+          'deprecated',
+          'experimental'
+        ]);
     var deprecated = html.attributes['deprecated'] == 'true';
+    var experimental = html.attributes['experimental'] == 'true';
     var optional = false;
     var optionalString = html.attributes['optional'];
     if (optionalString != null) {
@@ -500,8 +511,11 @@
     }
     var value = html.attributes['value'];
     var type = processContentsAsType(html, context);
-    return TypeObjectField(name!, type, html,
-        optional: optional, value: value, deprecated: deprecated);
+    return TypeObjectField(name, type, html,
+        optional: optional,
+        value: value,
+        deprecated: deprecated,
+        experimental: experimental);
   }
 
   /// Create a [TypeObject] from an HTML description.
diff --git a/pkg/analyzer_plugin/tool/spec/to_html.dart b/pkg/analyzer_plugin/tool/spec/to_html.dart
index 52fbdbe..852a05f 100644
--- a/pkg/analyzer_plugin/tool/spec/to_html.dart
+++ b/pkg/analyzer_plugin/tool/spec/to_html.dart
@@ -644,6 +644,9 @@
 
   @override
   void visitTypeObjectField(TypeObjectField typeObjectField) {
+    if (typeObjectField.experimental) {
+      return;
+    }
     dt('field', () {
       b(() {
         if (typeObjectField.deprecated) {
@@ -748,6 +751,7 @@
     writeln('{');
     indent(() {
       for (var field in typeObject.fields) {
+        if (field.experimental) continue;
         write('"');
         final fieldsToBold = this.fieldsToBold;
         if (fieldsToBold != null && fieldsToBold.contains(field.name)) {
diff --git a/runtime/vm/os_thread.h b/runtime/vm/os_thread.h
index 1f6a0e3..b1019e8 100644
--- a/runtime/vm/os_thread.h
+++ b/runtime/vm/os_thread.h
@@ -305,9 +305,8 @@
 
   friend class IsolateGroup;  // to access set_thread(Thread*).
   friend class OSThreadIterator;
-  friend class ThreadInterrupterFuchsia;
-  friend class ThreadInterrupterMacOS;
   friend class ThreadInterrupterWin;
+  friend class ThreadInterrupterFuchsia;
   friend class ThreadPool;  // to access owning_thread_pool_worker_
 };
 
diff --git a/runtime/vm/signal_handler_macos.cc b/runtime/vm/signal_handler_macos.cc
index 0e0c591..70e5319 100644
--- a/runtime/vm/signal_handler_macos.cc
+++ b/runtime/vm/signal_handler_macos.cc
@@ -91,11 +91,24 @@
 }
 
 void SignalHandler::Install(SignalAction action) {
-  // Nothing to do on MacOS.
+  struct sigaction act = {};
+  act.sa_handler = NULL;
+  act.sa_sigaction = action;
+  sigemptyset(&act.sa_mask);
+  act.sa_flags = SA_RESTART | SA_SIGINFO;
+  int r = sigaction(SIGPROF, &act, NULL);
+  ASSERT(r == 0);
 }
 
 void SignalHandler::Remove() {
-  // Nothing to do on MacOS.
+  // Ignore future SIGPROF signals because by default SIGPROF will terminate
+  // the process and we may have some signals in flight.
+  struct sigaction act = {};
+  act.sa_handler = SIG_IGN;
+  sigemptyset(&act.sa_mask);
+  act.sa_flags = 0;
+  int r = sigaction(SIGPROF, &act, NULL);
+  ASSERT(r == 0);
 }
 
 }  // namespace dart
diff --git a/runtime/vm/thread_interrupter.cc b/runtime/vm/thread_interrupter.cc
index 978b428..be990ab 100644
--- a/runtime/vm/thread_interrupter.cc
+++ b/runtime/vm/thread_interrupter.cc
@@ -66,6 +66,15 @@
 
 void ThreadInterrupter::Startup() {
   ASSERT(initialized_);
+  if (IsDebuggerAttached()) {
+    MonitorLocker shutdown_ml(monitor_);
+    shutdown_ = true;
+    if (FLAG_trace_thread_interrupter) {
+      OS::PrintErr(
+          "ThreadInterrupter disabled because a debugger is attached.\n");
+    }
+    return;
+  }
   if (FLAG_trace_thread_interrupter) {
     OS::PrintErr("ThreadInterrupter starting up.\n");
   }
diff --git a/runtime/vm/thread_interrupter.h b/runtime/vm/thread_interrupter.h
index 8921ebe..c5d770e 100644
--- a/runtime/vm/thread_interrupter.h
+++ b/runtime/vm/thread_interrupter.h
@@ -102,6 +102,8 @@
   static std::atomic<intptr_t> sample_buffer_lock_;
   static std::atomic<intptr_t> sample_buffer_waiters_;
 
+  static bool IsDebuggerAttached();
+
   static bool InDeepSleep() {
     return current_wait_time_ == Monitor::kNoTimeout;
   }
diff --git a/runtime/vm/thread_interrupter_android.cc b/runtime/vm/thread_interrupter_android.cc
index 2f8ed98..dbdd331 100644
--- a/runtime/vm/thread_interrupter_android.cc
+++ b/runtime/vm/thread_interrupter_android.cc
@@ -61,6 +61,10 @@
 #endif
 }  // namespace
 
+bool ThreadInterrupter::IsDebuggerAttached() {
+  return false;
+}
+
 void ThreadInterrupter::InterruptThread(OSThread* thread) {
   if (FLAG_trace_thread_interrupter) {
     OS::PrintErr("ThreadInterrupter interrupting %p\n",
diff --git a/runtime/vm/thread_interrupter_fuchsia.cc b/runtime/vm/thread_interrupter_fuchsia.cc
index 235bbed..b295569 100644
--- a/runtime/vm/thread_interrupter_fuchsia.cc
+++ b/runtime/vm/thread_interrupter_fuchsia.cc
@@ -227,6 +227,10 @@
   }
 };
 
+bool ThreadInterrupter::IsDebuggerAttached() {
+  return false;
+}
+
 void ThreadInterrupter::InterruptThread(OSThread* thread) {
   if (FLAG_trace_thread_interrupter) {
     OS::PrintErr("ThreadInterrupter suspending %p\n",
diff --git a/runtime/vm/thread_interrupter_linux.cc b/runtime/vm/thread_interrupter_linux.cc
index 5d7661d..ee623db 100644
--- a/runtime/vm/thread_interrupter_linux.cc
+++ b/runtime/vm/thread_interrupter_linux.cc
@@ -48,6 +48,10 @@
   }
 };
 
+bool ThreadInterrupter::IsDebuggerAttached() {
+  return false;
+}
+
 void ThreadInterrupter::InterruptThread(OSThread* thread) {
   if (FLAG_trace_thread_interrupter) {
     OS::PrintErr("ThreadInterrupter interrupting %p\n",
diff --git a/runtime/vm/thread_interrupter_macos.cc b/runtime/vm/thread_interrupter_macos.cc
index 4a1cb85..ba9ce5a 100644
--- a/runtime/vm/thread_interrupter_macos.cc
+++ b/runtime/vm/thread_interrupter_macos.cc
@@ -5,15 +5,12 @@
 #include "platform/globals.h"
 #if defined(DART_HOST_OS_MACOS)
 
-#include <assert.h>            // NOLINT
-#include <errno.h>             // NOLINT
-#include <mach/kern_return.h>  // NOLINT
-#include <mach/mach.h>         // NOLINT
-#include <mach/thread_act.h>   // NOLINT
-#include <stdbool.h>           // NOLINT
-#include <sys/sysctl.h>        // NOLINT
-#include <sys/types.h>         // NOLINT
-#include <unistd.h>            // NOLINT
+#include <assert.h>      // NOLINT
+#include <errno.h>       // NOLINT
+#include <stdbool.h>     // NOLINT
+#include <sys/sysctl.h>  // NOLINT
+#include <sys/types.h>   // NOLINT
+#include <unistd.h>      // NOLINT
 
 #include "vm/flags.h"
 #include "vm/os.h"
@@ -27,110 +24,70 @@
 
 DECLARE_FLAG(bool, trace_thread_interrupter);
 
-#if defined(HOST_ARCH_X64)
-#define THREAD_STATE_FLAVOR x86_THREAD_STATE64
-#define THREAD_STATE_FLAVOR_SIZE x86_THREAD_STATE64_COUNT
-typedef x86_thread_state64_t thread_state_flavor_t;
-#elif defined(HOST_ARCH_ARM64)
-#define THREAD_STATE_FLAVOR ARM_THREAD_STATE64
-#define THREAD_STATE_FLAVOR_SIZE ARM_THREAD_STATE64_COUNT
-typedef arm_thread_state64_t thread_state_flavor_t;
-#elif defined(HOST_ARCH_ARM)
-#define THREAD_STATE_FLAVOR ARM_THREAD_STATE32
-#define THREAD_STATE_FLAVOR_SIZE ARM_THREAD_STATE32_COUNT
-typedef arm_thread_state32_t thread_state_flavor_t;
-#else
-#error "Unsupported architecture."
-#endif  // HOST_ARCH_...
+// Returns true if the current process is being debugged (either
+// running under the debugger or has a debugger attached post facto).
+// Code from https://developer.apple.com/library/content/qa/qa1361/_index.html
+bool ThreadInterrupter::IsDebuggerAttached() {
+  struct kinfo_proc info;
+  // Initialize the flags so that, if sysctl fails for some bizarre
+  // reason, we get a predictable result.
+  info.kp_proc.p_flag = 0;
+  // Initialize mib, which tells sysctl the info we want, in this case
+  // we're looking for information about a specific process ID.
+  int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid()};
+  size_t size = sizeof(info);
 
-class ThreadInterrupterMacOS {
+  // Call sysctl.
+  size = sizeof(info);
+  int junk = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0);
+  ASSERT(junk == 0);
+  // We're being debugged if the P_TRACED flag is set.
+  return ((info.kp_proc.p_flag & P_TRACED) != 0);
+}
+
+class ThreadInterrupterMacOS : public AllStatic {
  public:
-  explicit ThreadInterrupterMacOS(OSThread* os_thread) : os_thread_(os_thread) {
-    ASSERT(os_thread != nullptr);
-    mach_thread_ = pthread_mach_thread_np(os_thread->id());
-    ASSERT(reinterpret_cast<void*>(mach_thread_) != nullptr);
-    res = thread_suspend(mach_thread_);
-  }
-
-  void CollectSample() {
-    if (res != KERN_SUCCESS) {
+  static void ThreadInterruptSignalHandler(int signal,
+                                           siginfo_t* info,
+                                           void* context_) {
+    if (signal != SIGPROF) {
       return;
     }
-    auto count = static_cast<mach_msg_type_number_t>(THREAD_STATE_FLAVOR_SIZE);
-    thread_state_flavor_t state;
-    kern_return_t res =
-        thread_get_state(mach_thread_, THREAD_STATE_FLAVOR,
-                         reinterpret_cast<thread_state_t>(&state), &count);
-    ASSERT(res == KERN_SUCCESS);
-    Thread* thread = static_cast<Thread*>(os_thread_->thread());
-    if (thread == nullptr) {
+    Thread* thread = Thread::Current();
+    if (thread == NULL) {
       return;
     }
-    Profiler::SampleThread(thread, ProcessState(state));
-  }
-
-  ~ThreadInterrupterMacOS() {
-    if (res != KERN_SUCCESS) {
+    ThreadInterrupter::SampleBufferWriterScope scope;
+    if (!scope.CanSample()) {
       return;
     }
-    res = thread_resume(mach_thread_);
-    ASSERT(res == KERN_SUCCESS);
-  }
-
- private:
-  static InterruptedThreadState ProcessState(thread_state_flavor_t state) {
+    // Extract thread state.
+    ucontext_t* context = reinterpret_cast<ucontext_t*>(context_);
+    mcontext_t mcontext = context->uc_mcontext;
     InterruptedThreadState its;
-#if defined(HOST_ARCH_X64)
-    its.pc = state.__rip;
-    its.fp = state.__rbp;
-    its.csp = state.__rsp;
-    its.dsp = state.__rsp;
-    its.lr = 0;
-#elif defined(HOST_ARCH_ARM64)
-    its.pc = state.__pc;
-    its.fp = state.__fp;
-    its.csp = state.__sp;
-    its.dsp = state.__sp;
-    its.lr = state.__lr;
-#elif defined(HOST_ARCH_ARM)
-    its.pc = state.__pc;
-    its.fp = state.__fp;
-    its.csp = state.__sp;
-    its.dsp = state.__sp;
-    its.lr = state.__lr;
-#endif  // HOST_ARCH_...
-
-#if defined(TARGET_ARCH_ARM64) && !defined(USING_SIMULATOR)
-    its.dsp = state.__x[SPREG];
-#endif
-    return its;
+    its.pc = SignalHandler::GetProgramCounter(mcontext);
+    its.fp = SignalHandler::GetFramePointer(mcontext);
+    its.csp = SignalHandler::GetCStackPointer(mcontext);
+    its.dsp = SignalHandler::GetDartStackPointer(mcontext);
+    its.lr = SignalHandler::GetLinkRegister(mcontext);
+    Profiler::SampleThread(thread, its);
   }
-
-  kern_return_t res;
-  OSThread* os_thread_;
-  mach_port_t mach_thread_;
 };
 
-void ThreadInterrupter::InterruptThread(OSThread* os_thread) {
-  ASSERT(!OSThread::Compare(OSThread::GetCurrentThreadId(), os_thread->id()));
+void ThreadInterrupter::InterruptThread(OSThread* thread) {
   if (FLAG_trace_thread_interrupter) {
-    OS::PrintErr("ThreadInterrupter interrupting %p\n", os_thread->id());
+    OS::PrintErr("ThreadInterrupter interrupting %p\n", thread->id());
   }
-
-  ThreadInterrupter::SampleBufferWriterScope scope;
-  if (!scope.CanSample()) {
-    return;
-  }
-  ThreadInterrupterMacOS interrupter(os_thread);
-  interrupter.CollectSample();
+  int result = pthread_kill(thread->id(), SIGPROF);
+  ASSERT((result == 0) || (result == ESRCH));
 }
 
 void ThreadInterrupter::InstallSignalHandler() {
-  // Nothing to do on MacOS.
+  SignalHandler::Install(&ThreadInterrupterMacOS::ThreadInterruptSignalHandler);
 }
 
 void ThreadInterrupter::RemoveSignalHandler() {
-  // Nothing to do on MacOS.
+  SignalHandler::Remove();
 }
 
 #endif  // !PRODUCT
diff --git a/runtime/vm/thread_interrupter_win.cc b/runtime/vm/thread_interrupter_win.cc
index 3db5023..bfbf5d1 100644
--- a/runtime/vm/thread_interrupter_win.cc
+++ b/runtime/vm/thread_interrupter_win.cc
@@ -90,6 +90,10 @@
   }
 };
 
+bool ThreadInterrupter::IsDebuggerAttached() {
+  return false;
+}
+
 void ThreadInterrupter::InterruptThread(OSThread* thread) {
   if (FLAG_trace_thread_interrupter) {
     OS::PrintErr("ThreadInterrupter suspending %p\n",
diff --git a/tools/VERSION b/tools/VERSION
index d6d0abc..ade4524 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 15
 PATCH 0
-PRERELEASE 216
+PRERELEASE 217
 PRERELEASE_PATCH 0
\ No newline at end of file