Version 2.16.0-116.0.dev

Merge commit 'a9b33cfcd286f6467b1aa71270737908886a6f55' into 'dev'
diff --git a/DEPS b/DEPS
index 66d0909..2b0e05f 100644
--- a/DEPS
+++ b/DEPS
@@ -133,7 +133,7 @@
   "mockito_rev": "d39ac507483b9891165e422ec98d9fb480037c8b",
   "oauth2_rev": "7cd3284049fe5badbec9f2bea2afc41d14c01057",
   "package_config_rev": "fb736aa12316dd2d882b202a438a6946a4b4bea0",
-  "path_rev": "c20d73c3516d3a0061c90f14b761ff532b9bf707",
+  "path_rev": "baedce9d2ca11ea2cdf54395a74eb038087777a4",
   "pedantic_rev": "66f2f6c27581c7936482e83be80b27be2719901c",
   "platform_rev": "1ffad63428bbd1b3ecaa15926bacfb724023648c",
   "ply_rev": "604b32590ffad5cbb82e4afef1d305512d06ae93",
diff --git a/pkg/analyzer/lib/src/dart/resolver/ast_rewrite.dart b/pkg/analyzer/lib/src/dart/resolver/ast_rewrite.dart
index 25dfe1a..61f364e 100644
--- a/pkg/analyzer/lib/src/dart/resolver/ast_rewrite.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/ast_rewrite.dart
@@ -232,7 +232,7 @@
       return node;
     }
     if (parent is CommentReference) {
-      // TODO(srawlins): This probably should be rewritten to a
+      // TODO(srawlins): This probably should be allowed to be rewritten to a
       // [ConstructorReference] at some point.
       return node;
     }
@@ -281,6 +281,11 @@
       // `Type`.
       return node;
     }
+    if (node.parent is CommentReference) {
+      // TODO(srawlins): This probably should be allowed to be rewritten to a
+      // [ConstructorReference] at some point.
+      return node;
+    }
     var receiver = node.target!;
 
     Identifier receiverIdentifier;
diff --git a/runtime/bin/dart_embedder_api_impl.cc b/runtime/bin/dart_embedder_api_impl.cc
index 88c641f..9ba84e9 100644
--- a/runtime/bin/dart_embedder_api_impl.cc
+++ b/runtime/bin/dart_embedder_api_impl.cc
@@ -17,17 +17,17 @@
 namespace embedder {
 
 static char* MallocFormatedString(const char* format, ...) {
-  va_list args;
-  va_start(args, format);
-  intptr_t len = vsnprintf(NULL, 0, format, args);
-  va_end(args);
+  va_list measure_args;
+  va_start(measure_args, format);
+  intptr_t len = vsnprintf(NULL, 0, format, measure_args);
+  va_end(measure_args);
 
   char* buffer = reinterpret_cast<char*>(malloc(len + 1));
   MSAN_UNPOISON(buffer, (len + 1));
-  va_list args2;
-  va_start(args2, format);
-  vsnprintf(buffer, (len + 1), format, args2);
-  va_end(args2);
+  va_list print_args;
+  va_start(print_args, format);
+  vsnprintf(buffer, (len + 1), format, print_args);
+  va_end(print_args);
   return buffer;
 }
 
diff --git a/runtime/bin/dartutils.cc b/runtime/bin/dartutils.cc
index 565753d..05a500e 100644
--- a/runtime/bin/dartutils.cc
+++ b/runtime/bin/dartutils.cc
@@ -729,17 +729,17 @@
 }
 
 Dart_Handle DartUtils::NewError(const char* format, ...) {
-  va_list args;
-  va_start(args, format);
-  intptr_t len = vsnprintf(NULL, 0, format, args);
-  va_end(args);
+  va_list measure_args;
+  va_start(measure_args, format);
+  intptr_t len = vsnprintf(NULL, 0, format, measure_args);
+  va_end(measure_args);
 
   char* buffer = reinterpret_cast<char*>(Dart_ScopeAllocate(len + 1));
   MSAN_UNPOISON(buffer, (len + 1));
-  va_list args2;
-  va_start(args2, format);
-  vsnprintf(buffer, (len + 1), format, args2);
-  va_end(args2);
+  va_list print_args;
+  va_start(print_args, format);
+  vsnprintf(buffer, (len + 1), format, print_args);
+  va_end(print_args);
 
   return Dart_NewApiError(buffer);
 }
@@ -749,17 +749,17 @@
 }
 
 Dart_Handle DartUtils::NewStringFormatted(const char* format, ...) {
-  va_list args;
-  va_start(args, format);
-  intptr_t len = vsnprintf(NULL, 0, format, args);
-  va_end(args);
+  va_list measure_args;
+  va_start(measure_args, format);
+  intptr_t len = vsnprintf(NULL, 0, format, measure_args);
+  va_end(measure_args);
 
   char* buffer = reinterpret_cast<char*>(Dart_ScopeAllocate(len + 1));
   MSAN_UNPOISON(buffer, (len + 1));
-  va_list args2;
-  va_start(args2, format);
-  vsnprintf(buffer, (len + 1), format, args2);
-  va_end(args2);
+  va_list print_args;
+  va_start(print_args, format);
+  vsnprintf(buffer, (len + 1), format, print_args);
+  va_end(print_args);
 
   return NewString(buffer);
 }
diff --git a/runtime/platform/syslog_android.cc b/runtime/platform/syslog_android.cc
index 46930e9..e3d4599 100644
--- a/runtime/platform/syslog_android.cc
+++ b/runtime/platform/syslog_android.cc
@@ -19,18 +19,32 @@
   // If we launch the DartVM inside "adb shell" we will only get messages
   // (critical ones or not) if we print them to stdout/stderr.
   // We also log using android's logging system.
-  vprintf(format, args);
+  va_list stdio_args;
+  va_copy(stdio_args, args);
+  vprintf(format, stdio_args);
   fflush(stdout);
-  __android_log_vprint(ANDROID_LOG_INFO, "Dart", format, args);
+  va_end(stdio_args);
+
+  va_list log_args;
+  va_copy(log_args, args);
+  __android_log_vprint(ANDROID_LOG_INFO, "Dart", format, log_args);
+  va_end(log_args);
 }
 
 void Syslog::VPrintErr(const char* format, va_list args) {
   // If we launch the DartVM inside "adb shell" we will only get messages
   // (critical ones or not) if we print them to stdout/stderr.
   // We also log using android's logging system.
-  vfprintf(stderr, format, args);
+  va_list stdio_args;
+  va_copy(stdio_args, args);
+  vfprintf(stderr, format, stdio_args);
   fflush(stderr);
-  __android_log_vprint(ANDROID_LOG_ERROR, "Dart", format, args);
+  va_end(stdio_args);
+
+  va_list log_args;
+  va_copy(log_args, args);
+  __android_log_vprint(ANDROID_LOG_ERROR, "Dart", format, log_args);
+  va_end(log_args);
 }
 
 }  // namespace dart
diff --git a/runtime/vm/compiler/assembler/disassembler.cc b/runtime/vm/compiler/assembler/disassembler.cc
index e9b082f..ac67f41 100644
--- a/runtime/vm/compiler/assembler/disassembler.cc
+++ b/runtime/vm/compiler/assembler/disassembler.cc
@@ -80,14 +80,16 @@
 }
 
 void DisassembleToJSONStream::Print(const char* format, ...) {
-  va_list args;
-  va_start(args, format);
-  intptr_t len = Utils::VSNPrint(NULL, 0, format, args);
-  va_end(args);
+  va_list measure_args;
+  va_start(measure_args, format);
+  intptr_t len = Utils::VSNPrint(NULL, 0, format, measure_args);
+  va_end(measure_args);
+
   char* p = reinterpret_cast<char*>(malloc(len + 1));
-  va_start(args, format);
-  intptr_t len2 = Utils::VSNPrint(p, len, format, args);
-  va_end(args);
+  va_list print_args;
+  va_start(print_args, format);
+  intptr_t len2 = Utils::VSNPrint(p, len, format, print_args);
+  va_end(print_args);
   ASSERT(len == len2);
   for (intptr_t i = 0; i < len; i++) {
     if (p[i] == '\n' || p[i] == '\r') {
@@ -134,10 +136,10 @@
   if (overflowed_) {
     return;
   }
-  va_list args;
-  va_start(args, format);
-  intptr_t len = Utils::VSNPrint(NULL, 0, format, args);
-  va_end(args);
+  va_list measure_args;
+  va_start(measure_args, format);
+  intptr_t len = Utils::VSNPrint(NULL, 0, format, measure_args);
+  va_end(measure_args);
   if (remaining_ < len + 100) {
     *buffer_++ = '.';
     *buffer_++ = '.';
@@ -147,9 +149,10 @@
     overflowed_ = true;
     return;
   }
-  va_start(args, format);
-  intptr_t len2 = Utils::VSNPrint(buffer_, len, format, args);
-  va_end(args);
+  va_list print_args;
+  va_start(print_args, format);
+  intptr_t len2 = Utils::VSNPrint(buffer_, len, format, print_args);
+  va_end(print_args);
   ASSERT(len == len2);
   buffer_ += len;
   remaining_ -= len;
diff --git a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
index b37c682..1124ea1 100644
--- a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
@@ -1244,33 +1244,44 @@
 }
 
 Fragment BaseFlowGraphBuilder::RecordCoverage(TokenPosition position) {
+  return RecordCoverageImpl(position, false /** is_branch_coverage **/);
+}
+
+Fragment BaseFlowGraphBuilder::RecordBranchCoverage(TokenPosition position) {
+  return RecordCoverageImpl(position, true /** is_branch_coverage **/);
+}
+
+Fragment BaseFlowGraphBuilder::RecordCoverageImpl(TokenPosition position,
+                                                  bool is_branch_coverage) {
   Fragment instructions;
-  if (SupportsCoverage()) {
-    const intptr_t coverage_index = GetCoverageIndexFor(position);
-    instructions <<= new (Z) RecordCoverageInstr(
-        coverage_array(), coverage_index, InstructionSource(position));
-  }
+  if (!SupportsCoverage()) return instructions;
+  if (!position.IsReal()) return instructions;
+  if (is_branch_coverage && !IG->branch_coverage()) return instructions;
+
+  const intptr_t coverage_index =
+      GetCoverageIndexFor(position.EncodeCoveragePosition(is_branch_coverage));
+  instructions <<= new (Z) RecordCoverageInstr(coverage_array(), coverage_index,
+                                               InstructionSource(position));
   return instructions;
 }
 
-intptr_t BaseFlowGraphBuilder::GetCoverageIndexFor(TokenPosition token_pos) {
+intptr_t BaseFlowGraphBuilder::GetCoverageIndexFor(intptr_t encoded_position) {
   if (coverage_array_.IsNull()) {
-    // We have not yet created coverage_array, this is the first time
-    // we are building the graph for this function. Collect coverage
-    // positions.
+    // We have not yet created coverage_array, this is the first time we are
+    // building the graph for this function. Collect coverage positions.
     for (intptr_t i = 0; i < coverage_array_positions_.length(); i++) {
-      if (coverage_array_positions_.At(i) == token_pos) {
+      if (coverage_array_positions_.At(i) == encoded_position) {
         return 2 * i + 1;
       }
     }
     const auto index = 2 * coverage_array_positions_.length() + 1;
-    coverage_array_positions_.Add(token_pos);
+    coverage_array_positions_.Add(encoded_position);
     return index;
   }
 
   for (intptr_t i = 0; i < coverage_array_.Length(); i += 2) {
-    if (TokenPosition::Deserialize(Smi::Value(
-            static_cast<SmiPtr>(coverage_array_.At(i)))) == token_pos) {
+    if (Smi::Value(static_cast<SmiPtr>(coverage_array_.At(i))) ==
+        encoded_position) {
       return i + 1;
     }
   }
@@ -1294,7 +1305,7 @@
 
   Smi& value = Smi::Handle();
   for (intptr_t i = 0; i < coverage_array_positions_.length(); i++) {
-    value = Smi::New(coverage_array_positions_[i].Serialize());
+    value = Smi::New(coverage_array_positions_[i]);
     coverage_array_.SetAt(2 * i, value);
     value = Smi::New(0);  // no coverage recorded.
     coverage_array_.SetAt(2 * i + 1, value);
diff --git a/runtime/vm/compiler/frontend/base_flow_graph_builder.h b/runtime/vm/compiler/frontend/base_flow_graph_builder.h
index b0597b8..5aa008b 100644
--- a/runtime/vm/compiler/frontend/base_flow_graph_builder.h
+++ b/runtime/vm/compiler/frontend/base_flow_graph_builder.h
@@ -166,7 +166,6 @@
 
   const Array& coverage_array() const { return coverage_array_; }
 
-  intptr_t GetCoverageIndexFor(TokenPosition token_pos);
   void FinalizeCoverageArray();
 
   Fragment LoadField(const Field& field, bool calls_initializer);
@@ -473,6 +472,7 @@
 
   // Records coverage for this position, if the current VM mode supports it.
   Fragment RecordCoverage(TokenPosition position);
+  Fragment RecordBranchCoverage(TokenPosition position);
 
   // Returns whether this function has a saved arguments descriptor array.
   bool has_saved_args_desc_array() {
@@ -487,6 +487,8 @@
 
  protected:
   intptr_t AllocateBlockId() { return ++last_used_block_id_; }
+  Fragment RecordCoverageImpl(TokenPosition position, bool is_branch_coverage);
+  intptr_t GetCoverageIndexFor(intptr_t encoded_position);
 
   const ParsedFunction* parsed_function_;
   const Function& function_;
@@ -507,7 +509,7 @@
   const bool inlining_unchecked_entry_;
   const Array& saved_args_desc_array_;
 
-  GrowableArray<TokenPosition> coverage_array_positions_;
+  GrowableArray<intptr_t> coverage_array_positions_;
   Array& coverage_array_;
 
   friend class StreamingFlowGraphBuilder;
diff --git a/runtime/vm/json_stream.cc b/runtime/vm/json_stream.cc
index 01b6c5f..dfac508 100644
--- a/runtime/vm/json_stream.cc
+++ b/runtime/vm/json_stream.cc
@@ -164,16 +164,16 @@
     JSONObject data(&jsobj, "data");
     PrintRequest(&data, this);
     if (details_format != NULL) {
-      va_list args;
-      va_start(args, details_format);
-      intptr_t len = Utils::VSNPrint(NULL, 0, details_format, args);
-      va_end(args);
+      va_list measure_args;
+      va_start(measure_args, details_format);
+      intptr_t len = Utils::VSNPrint(NULL, 0, details_format, measure_args);
+      va_end(measure_args);
 
       char* buffer = Thread::Current()->zone()->Alloc<char>(len + 1);
-      va_list args2;
-      va_start(args2, details_format);
-      Utils::VSNPrint(buffer, (len + 1), details_format, args2);
-      va_end(args2);
+      va_list print_args;
+      va_start(print_args, details_format);
+      Utils::VSNPrint(buffer, (len + 1), details_format, print_args);
+      va_end(print_args);
       data.AddProperty("details", buffer);
     }
   }
diff --git a/runtime/vm/service_test.cc b/runtime/vm/service_test.cc
index 2800565..751bb7e 100644
--- a/runtime/vm/service_test.cc
+++ b/runtime/vm/service_test.cc
@@ -105,16 +105,16 @@
 }
 
 static ArrayPtr EvalF(Dart_Handle lib, const char* fmt, ...) {
-  va_list args;
-  va_start(args, fmt);
-  intptr_t len = Utils::VSNPrint(NULL, 0, fmt, args);
-  va_end(args);
+  va_list messure_args;
+  va_start(messure_args, fmt);
+  intptr_t len = Utils::VSNPrint(NULL, 0, fmt, messure_args);
+  va_end(messure_args);
 
   char* buffer = Thread::Current()->zone()->Alloc<char>(len + 1);
-  va_list args2;
-  va_start(args2, fmt);
-  Utils::VSNPrint(buffer, (len + 1), fmt, args2);
-  va_end(args2);
+  va_list print_args;
+  va_start(print_args, fmt);
+  Utils::VSNPrint(buffer, (len + 1), fmt, print_args);
+  va_end(print_args);
 
   return Eval(lib, buffer);
 }
diff --git a/runtime/vm/source_report.cc b/runtime/vm/source_report.cc
index 12f6096..b826aa9 100644
--- a/runtime/vm/source_report.cc
+++ b/runtime/vm/source_report.cc
@@ -346,11 +346,14 @@
   const Array& coverage_array = Array::Handle(function.GetCoverageArray());
   if (!coverage_array.IsNull()) {
     for (intptr_t i = 0; i < coverage_array.Length(); i += 2) {
-      const TokenPosition token_pos = TokenPosition::Deserialize(
-          Smi::Value(Smi::RawCast(coverage_array.At(i))));
-      const bool was_executed =
-          Smi::Value(Smi::RawCast(coverage_array.At(i + 1))) != 0;
-      update_coverage(token_pos, was_executed);
+      bool is_branch_coverage;
+      const TokenPosition token_pos = TokenPosition::DecodeCoveragePosition(
+          Smi::Value(Smi::RawCast(coverage_array.At(i))), &is_branch_coverage);
+      if (!is_branch_coverage) {
+        const bool was_executed =
+            Smi::Value(Smi::RawCast(coverage_array.At(i + 1))) != 0;
+        update_coverage(token_pos, was_executed);
+      }
     }
   }
 
diff --git a/runtime/vm/timeline.cc b/runtime/vm/timeline.cc
index 386178e..13f4ab9 100644
--- a/runtime/vm/timeline.cc
+++ b/runtime/vm/timeline.cc
@@ -349,14 +349,16 @@
                                             va_list args) {
   ASSERT(i >= 0);
   ASSERT(i < length_);
-  va_list args2;
-  va_copy(args2, args);
-  intptr_t len = Utils::VSNPrint(NULL, 0, fmt, args);
-  va_end(args);
+  va_list measure_args;
+  va_copy(measure_args, args);
+  intptr_t len = Utils::VSNPrint(NULL, 0, fmt, measure_args);
+  va_end(measure_args);
 
   char* buffer = reinterpret_cast<char*>(malloc(len + 1));
-  Utils::VSNPrint(buffer, (len + 1), fmt, args2);
-  va_end(args2);
+  va_list print_args;
+  va_copy(print_args, args);
+  Utils::VSNPrint(buffer, (len + 1), fmt, print_args);
+  va_end(print_args);
 
   SetArgument(i, name, buffer);
 }
@@ -546,6 +548,7 @@
   va_list args;
   va_start(args, fmt);
   arguments_.FormatArgument(i, name, fmt, args);
+  va_end(args);
 }
 
 void TimelineEvent::Complete() {
@@ -846,6 +849,7 @@
   va_list args;
   va_start(args, fmt);
   arguments_.FormatArgument(i, name, fmt, args);
+  va_end(args);
 }
 
 void TimelineEventScope::StealArguments(TimelineEvent* event) {
diff --git a/runtime/vm/token_position.cc b/runtime/vm/token_position.cc
index 14f7058..88b27c1 100644
--- a/runtime/vm/token_position.cc
+++ b/runtime/vm/token_position.cc
@@ -21,6 +21,19 @@
   return static_cast<int32_t>(value_);
 }
 
+intptr_t TokenPosition::EncodeCoveragePosition(bool is_branch_coverage) {
+  // Normal coverage positions are encoded as 2 * pos, and branch coverage are
+  // encoded as 2 * pos + 1.
+  intptr_t encoded_position = 2 * static_cast<intptr_t>(value_);
+  return is_branch_coverage ? encoded_position + 1 : encoded_position;
+}
+
+TokenPosition TokenPosition::DecodeCoveragePosition(intptr_t encoded_position,
+                                                    bool* is_branch_coverage) {
+  *is_branch_coverage = ((encoded_position % 2) == 1);
+  return TokenPosition(encoded_position / 2);
+}
+
 #define DEFINE_VALUES(name, value)                                             \
   const TokenPosition TokenPosition::k##name(value);
 SENTINEL_TOKEN_DESCRIPTORS(DEFINE_VALUES);
diff --git a/runtime/vm/token_position.h b/runtime/vm/token_position.h
index 8dcf100..6778726 100644
--- a/runtime/vm/token_position.h
+++ b/runtime/vm/token_position.h
@@ -202,6 +202,13 @@
     return TokenPosition((kLastPos - 1) - value);
   }
 
+  // Encode the token position for storage in the coverage array.
+  intptr_t EncodeCoveragePosition(bool is_branch_coverage);
+
+  // Decode a token position that was stored in the coverage array.
+  static TokenPosition DecodeCoveragePosition(intptr_t encoded_position,
+                                              bool* is_branch_coverage);
+
   const char* ToCString() const;
 
  private:
diff --git a/runtime/vm/v8_snapshot_writer.cc b/runtime/vm/v8_snapshot_writer.cc
index 1a224df..2aaf1cb 100644
--- a/runtime/vm/v8_snapshot_writer.cc
+++ b/runtime/vm/v8_snapshot_writer.cc
@@ -279,6 +279,7 @@
   va_list args;
   va_start(args, fmt);
   const char* str = OS::VSCreate(zone_, fmt, args);
+  va_end(args);
   if (auto const kv = index_map_.Lookup(str)) {
     return kv->value;
   }
diff --git a/tools/VERSION b/tools/VERSION
index 7c980b1..05c9ce1 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 16
 PATCH 0
-PRERELEASE 115
+PRERELEASE 116
 PRERELEASE_PATCH 0
\ No newline at end of file