Version 2.15.0-89.0.dev

Merge commit '015c4e604a43b52071532a73056895930eada07c' into 'dev'
diff --git a/runtime/lib/isolate.cc b/runtime/lib/isolate.cc
index 5dfb8b8..0af5e76 100644
--- a/runtime/lib/isolate.cc
+++ b/runtime/lib/isolate.cc
@@ -655,7 +655,7 @@
     parent_isolate_ = nullptr;
 
     if (isolate == nullptr) {
-      FailedSpawn(error);
+      FailedSpawn(error, /*has_current_isolate=*/false);
       free(error);
       return;
     }
@@ -681,7 +681,7 @@
     parent_isolate_ = nullptr;
 
     if (isolate == nullptr) {
-      FailedSpawn(error, false);
+      FailedSpawn(error, /*has_current_isolate=*/false);
       free(error);
       return;
     }
@@ -854,7 +854,7 @@
     if (has_current_isolate) {
       ASSERT(IsolateGroup::Current() == state_->isolate_group());
       state_ = nullptr;
-    } else {
+    } else if (state_->isolate_group() != nullptr) {
       ASSERT(IsolateGroup::Current() == nullptr);
       const bool kBypassSafepoint = false;
       const bool result = Thread::EnterIsolateGroupAsHelper(
@@ -862,6 +862,10 @@
       ASSERT(result);
       state_ = nullptr;
       Thread::ExitIsolateGroupAsHelper(kBypassSafepoint);
+    } else {
+      // The state won't need a current isolate group, because it belongs to a
+      // [Isolate.spawnUri] call.
+      state_ = nullptr;
     }
   }
 
diff --git a/runtime/tests/vm/dart/regress_flutter89482_2_test.dart b/runtime/tests/vm/dart/regress_flutter89482_2_test.dart
new file mode 100644
index 0000000..7cd59be
--- /dev/null
+++ b/runtime/tests/vm/dart/regress_flutter89482_2_test.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2021, 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.
+
+void other([String something = "ok"]) {
+  print(something);
+}
+
+void main(List<String> args) {
+  Function x = other;
+  if (x is void Function({List<String> somethingElse})) {
+    x(somethingElse: args);
+  } else {
+    x();
+  }
+}
diff --git a/runtime/tests/vm/dart/regress_flutter89482_test.dart b/runtime/tests/vm/dart/regress_flutter89482_test.dart
new file mode 100644
index 0000000..9c39039
--- /dev/null
+++ b/runtime/tests/vm/dart/regress_flutter89482_test.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2021, 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.
+
+// This should not hit an ASSERT in the inliner that the call site has a
+// different number of named arguments.
+
+void other({String something = "ok"}) {
+  print(something);
+}
+
+void main(List<String> args) {
+  Function x = other;
+  if (x is void Function(List<String>)) {
+    x(args);
+  } else {
+    x();
+  }
+}
diff --git a/runtime/tests/vm/dart_2/regress_flutter89482_2_test.dart b/runtime/tests/vm/dart_2/regress_flutter89482_2_test.dart
new file mode 100644
index 0000000..7cd59be
--- /dev/null
+++ b/runtime/tests/vm/dart_2/regress_flutter89482_2_test.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2021, 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.
+
+void other([String something = "ok"]) {
+  print(something);
+}
+
+void main(List<String> args) {
+  Function x = other;
+  if (x is void Function({List<String> somethingElse})) {
+    x(somethingElse: args);
+  } else {
+    x();
+  }
+}
diff --git a/runtime/tests/vm/dart_2/regress_flutter89482_test.dart b/runtime/tests/vm/dart_2/regress_flutter89482_test.dart
new file mode 100644
index 0000000..9c39039
--- /dev/null
+++ b/runtime/tests/vm/dart_2/regress_flutter89482_test.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2021, 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.
+
+// This should not hit an ASSERT in the inliner that the call site has a
+// different number of named arguments.
+
+void other({String something = "ok"}) {
+  print(something);
+}
+
+void main(List<String> args) {
+  Function x = other;
+  if (x is void Function(List<String>)) {
+    x(args);
+  } else {
+    x();
+  }
+}
diff --git a/runtime/vm/compiler/backend/inliner.cc b/runtime/vm/compiler/backend/inliner.cc
index 112430d..09359cc 100644
--- a/runtime/vm/compiler/backend/inliner.cc
+++ b/runtime/vm/compiler/backend/inliner.cc
@@ -996,6 +996,17 @@
       return false;
     }
 
+    if ((function.HasOptionalPositionalParameters() ||
+         function.HasOptionalNamedParameters()) &&
+        !function.AreValidArguments(function.NumTypeParameters(),
+                                    arguments->length(), argument_names,
+                                    nullptr)) {
+      TRACE_INLINING(THR_Print("     Bailout: optional arg mismatch\n"));
+      PRINT_INLINING_TREE("Optional arg mismatch", &call_data->caller,
+                          &function, call_data->call);
+      return false;
+    }
+
     // Abort if this is a recursive occurrence.
     Definition* call = call_data->call;
     // Added 'volatile' works around a possible GCC 4.9 compiler bug.
@@ -1077,17 +1088,17 @@
           COMPILER_TIMINGS_TIMER_SCOPE(thread(), PopulateWithICData);
 
 #if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32)
-        if (CompilerState::Current().is_aot()) {
-          callee_graph->PopulateWithICData(parsed_function->function());
-        }
+          if (CompilerState::Current().is_aot()) {
+            callee_graph->PopulateWithICData(parsed_function->function());
+          }
 #endif
 
-        // If we inline a function which is intrinsified without a fall-through
-        // to IR code, we will not have any ICData attached, so we do it
-        // manually here.
-        if (!CompilerState::Current().is_aot() && function.is_intrinsic()) {
-          callee_graph->PopulateWithICData(parsed_function->function());
-        }
+          // If we inline a function which is intrinsified without a
+          // fall-through to IR code, we will not have any ICData attached, so
+          // we do it manually here.
+          if (!CompilerState::Current().is_aot() && function.is_intrinsic()) {
+            callee_graph->PopulateWithICData(parsed_function->function());
+          }
         }
 
         // The parameter stubs are a copy of the actual arguments providing
@@ -1584,10 +1595,14 @@
     intptr_t arg_count = arguments->length();
     intptr_t param_count = function.NumParameters();
     intptr_t fixed_param_count = function.num_fixed_parameters();
+    intptr_t argument_names_count =
+        (argument_names.IsNull()) ? 0 : argument_names.Length();
     ASSERT(fixed_param_count <= arg_count - first_arg_index);
     ASSERT(arg_count - first_arg_index <= param_count);
 
     if (function.HasOptionalPositionalParameters()) {
+      // Arguments mismatch: Caller supplied unsupported named argument.
+      ASSERT(argument_names_count == 0);
       // Create a stub for each optional positional parameters with an actual.
       for (intptr_t i = first_arg_index + fixed_param_count; i < arg_count;
            ++i) {
@@ -1609,12 +1624,10 @@
 
     ASSERT(function.HasOptionalNamedParameters());
 
-    // Passed arguments (not counting optional type args) must match fixed
-    // parameters plus named arguments.
-    intptr_t argument_names_count =
-        (argument_names.IsNull()) ? 0 : argument_names.Length();
-    ASSERT((arg_count - first_arg_index) ==
-           (fixed_param_count + argument_names_count));
+    const intptr_t positional_args =
+        arg_count - first_arg_index - argument_names_count;
+    // Arguments mismatch: Caller supplied unsupported positional argument.
+    ASSERT(positional_args == fixed_param_count);
 
     // Fast path when no optional named parameters are given.
     if (argument_names_count == 0) {
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index a787575..45b8262 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -67,6 +67,7 @@
 class CallSiteResetter;
 class CodeStatistics;
 class IsolateGroupReloadContext;
+class ObjectGraphCopier;
 
 #define REUSABLE_FORWARD_DECLARATION(name) class Reusable##name##HandleScope;
 REUSABLE_HANDLE_LIST(REUSABLE_FORWARD_DECLARATION)
@@ -864,6 +865,7 @@
   friend void UntaggedObject::Validate(IsolateGroup* isolate_group) const;
   friend class Closure;
   friend class InstanceDeserializationCluster;
+  friend class ObjectGraphCopier;  // For Object::InitializeObject
   friend class Simd128MessageDeserializationCluster;
   friend class OneByteString;
   friend class TwoByteString;
diff --git a/runtime/vm/object_graph_copy.cc b/runtime/vm/object_graph_copy.cc
index f5d8bc5..757815a 100644
--- a/runtime/vm/object_graph_copy.cc
+++ b/runtime/vm/object_graph_copy.cc
@@ -1858,12 +1858,11 @@
       auto to = fast_forward_map.raw_from_to_[i + 1];
       const uword tags = TagsFromUntaggedObject(from.untag());
       const intptr_t cid = UntaggedObject::ClassIdTag::decode(tags);
-      const intptr_t size = UntaggedObject::SizeTag::decode(tags);
       // External typed data is already initialized.
       if (!IsExternalTypedDataClassId(cid) && !IsTypedDataViewClassId(cid)) {
-        memset(reinterpret_cast<void*>(to.untag()), 0,
-               from.untag()->HeapSize());
-        SetNewSpaceTaggingWord(to, cid, size);
+        Object::InitializeObject(reinterpret_cast<uword>(to.untag()), cid,
+                                 from.untag()->HeapSize(),
+                                 /*compressed=*/cid != kContextCid);
         UpdateLengthField(cid, from, to);
       }
     }
diff --git a/tools/VERSION b/tools/VERSION
index 8b36375..fdc1fda 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 15
 PATCH 0
-PRERELEASE 88
+PRERELEASE 89
 PRERELEASE_PATCH 0
\ No newline at end of file