Version 2.14.0-157.0.dev

Merge commit 'a3767f7db86a85fcd6201e9357ad47b884002b66' into 'dev'
diff --git a/pkg/analyzer/lib/src/dart/ast/utilities.dart b/pkg/analyzer/lib/src/dart/ast/utilities.dart
index a2a8475..399b192 100644
--- a/pkg/analyzer/lib/src/dart/ast/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/ast/utilities.dart
@@ -92,7 +92,7 @@
       if (_lastClonedOffset <= token.offset) {
         _cloneTokens(_nextToClone ?? token, token.offset);
       }
-      return _clonedTokens[token]!;
+      return _clonedTokens[token] ?? _cloneSyntheticToken(token);
     } else {
       return token;
     }
@@ -1090,6 +1090,15 @@
           cloneNode(node.expression),
           cloneToken(node.semicolon));
 
+  /// Clones a synthetic token that isn't linked up to the rest of the token
+  /// list.
+  Token _cloneSyntheticToken(Token token) {
+    assert(token.isSynthetic);
+    assert(token.next == null);
+    assert(token.previous == null);
+    return token.copy();
+  }
+
   /// Clone all token starting from the given [token] up to a token that has
   /// offset greater then [stopAfter], and put mapping from originals to clones
   /// into [_clonedTokens].
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index e46200b..a4f9b42 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -485,15 +485,15 @@
       // This error is also reported in the body builder
       handleRecoverableError(messageInvalidSuperInInitializer,
           target.superKeyword, target.superKeyword);
-      return ast.superConstructorInvocation(
-          target.superKeyword, null, null, argumentList!);
+      return ast.superConstructorInvocation(target.superKeyword, null, null,
+          argumentList ?? _syntheticArgumentList(target.superKeyword));
     } else if (target is ThisExpression) {
       // TODO(danrubel): Consider generating this error in the parser
       // This error is also reported in the body builder
       handleRecoverableError(messageInvalidThisInInitializer,
           target.thisKeyword, target.thisKeyword);
-      return ast.redirectingConstructorInvocation(
-          target.thisKeyword, null, null, argumentList!);
+      return ast.redirectingConstructorInvocation(target.thisKeyword, null,
+          null, argumentList ?? _syntheticArgumentList(target.thisKeyword));
     }
     return null;
   }
@@ -3537,14 +3537,8 @@
       // TODO(paulberry): once we have visitor support for constructor
       // tear-offs, fall through and return a FunctionReference instead since
       // that should lead to better quality error recovery.
-      var syntheticOffset = typeArguments.rightBracket.end;
-      push(ast.functionExpressionInvocation(
-          receiver,
-          typeArguments,
-          ast.argumentList(
-              SyntheticToken(TokenType.OPEN_PAREN, syntheticOffset),
-              [],
-              SyntheticToken(TokenType.CLOSE_PAREN, syntheticOffset))));
+      push(ast.functionExpressionInvocation(receiver, typeArguments,
+          _syntheticArgumentList(typeArguments.rightBracket)));
       return;
     }
     push(ast.functionReference(
@@ -3871,6 +3865,14 @@
     return ast.variableDeclaration(name, equals, initializer);
   }
 
+  ArgumentList _syntheticArgumentList(Token precedingToken) {
+    int syntheticOffset = precedingToken.end;
+    return ast.argumentList(
+        SyntheticToken(TokenType.OPEN_PAREN, syntheticOffset),
+        [],
+        SyntheticToken(TokenType.CLOSE_PAREN, syntheticOffset));
+  }
+
   SimpleIdentifier _tmpSimpleIdentifier() {
     return ast.simpleIdentifier(
       StringToken(TokenType.STRING, '__tmp', -1),
diff --git a/pkg/analyzer/test/generated/simple_parser_test.dart b/pkg/analyzer/test/generated/simple_parser_test.dart
index 3a2881c..0198aa1 100644
--- a/pkg/analyzer/test/generated/simple_parser_test.dart
+++ b/pkg/analyzer/test/generated/simple_parser_test.dart
@@ -117,6 +117,33 @@
     expect(metadata.name.name, 'Foo.bar');
   }
 
+  void test_classDeclaration_invalid_super() {
+    parseCompilationUnit('''
+class C {
+  C() : super.const();
+}
+''', errors: [
+      expectedError(ParserErrorCode.INVALID_SUPER_IN_INITIALIZER, 18, 5),
+      expectedError(ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD, 24, 5),
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 24, 5),
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 29, 1),
+    ]);
+  }
+
+  void test_classDeclaration_invalid_this() {
+    parseCompilationUnit('''
+class C {
+  C() : this.const();
+}
+''', errors: [
+      expectedError(ParserErrorCode.MISSING_ASSIGNMENT_IN_INITIALIZER, 18, 4),
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 23, 5),
+      expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 23, 5),
+      expectedError(ParserErrorCode.CONST_METHOD, 23, 5),
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 28, 1),
+    ]);
+  }
+
   void test_method_name_notNull_37733() {
     // https://github.com/dart-lang/sdk/issues/37733
     var unit = parseCompilationUnit(r'class C { f(<T>()); }', errors: [
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_super_in_initializer_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_super_in_initializer_test.dart
new file mode 100644
index 0000000..8006c99
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/invalid_super_in_initializer_test.dart
@@ -0,0 +1,30 @@
+// 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.
+
+import 'package:analyzer/src/dart/error/syntactic_errors.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(InvalidSuperInInitializerTest);
+  });
+}
+
+@reflectiveTest
+class InvalidSuperInInitializerTest extends PubPackageResolutionTest {
+  test_constructor_name_is_keyword() async {
+    await assertErrorsInCode('''
+class C {
+  C() : super.const();
+}
+''', [
+      error(ParserErrorCode.INVALID_SUPER_IN_INITIALIZER, 18, 5),
+      error(ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD, 24, 5),
+      error(ParserErrorCode.MISSING_IDENTIFIER, 24, 5),
+      error(ParserErrorCode.MISSING_IDENTIFIER, 29, 1),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/test_all.dart b/pkg/analyzer/test/src/diagnostics/test_all.dart
index 78fe8d7..3cfce38 100644
--- a/pkg/analyzer/test/src/diagnostics/test_all.dart
+++ b/pkg/analyzer/test/src/diagnostics/test_all.dart
@@ -334,6 +334,7 @@
 import 'invalid_required_positional_param_test.dart'
     as invalid_required_positional_param;
 import 'invalid_sealed_annotation_test.dart' as invalid_sealed_annotation;
+import 'invalid_super_in_initializer_test.dart' as invalid_super_in_initializer;
 import 'invalid_super_invocation_test.dart' as invalid_super_invocation;
 import 'invalid_type_argument_in_const_list_test.dart'
     as invalid_type_argument_in_const_list;
@@ -918,6 +919,7 @@
     invalid_required_optional_positional_param.main();
     invalid_required_positional_param.main();
     invalid_sealed_annotation.main();
+    invalid_super_in_initializer.main();
     invalid_super_invocation.main();
     invalid_type_argument_in_const_list.main();
     invalid_type_argument_in_const_map.main();
diff --git a/pkg/vm/lib/transformations/ffi_definitions.dart b/pkg/vm/lib/transformations/ffi_definitions.dart
index 4ececb0..e84e660 100644
--- a/pkg/vm/lib/transformations/ffi_definitions.dart
+++ b/pkg/vm/lib/transformations/ffi_definitions.dart
@@ -568,7 +568,6 @@
         final sizeAnnotations = _getArraySizeAnnotations(m).toList();
         if (sizeAnnotations.length == 1) {
           final arrayDimensions = sizeAnnotations.single;
-          arrayDimensions.length;
           if (this.arrayDimensions(dartType) == arrayDimensions.length) {
             type = NativeTypeCfe(this, dartType,
                 compoundCache: compoundCache, arrayDimensions: arrayDimensions);
diff --git a/runtime/bin/ffi_test/ffi_test_functions.cc b/runtime/bin/ffi_test/ffi_test_functions.cc
index 49ab86f..3cf56b0 100644
--- a/runtime/bin/ffi_test/ffi_test_functions.cc
+++ b/runtime/bin/ffi_test/ffi_test_functions.cc
@@ -1113,6 +1113,16 @@
   return my_struct->someValue;
 }
 
+struct Struct46127 {
+  uint64_t val;
+};
+
+DART_EXPORT Struct46127 Regress46127() {
+  struct Struct46127 myStruct;
+  myStruct.val = 123;
+  return myStruct;
+}
+
 #pragma pack(push, 1)
 struct Struct3BytesPackedIntCopy {
   int8_t a0;
diff --git a/runtime/tests/vm/dart/disassemble_aot_test.dart b/runtime/tests/vm/dart/disassemble_aot_test.dart
index 1ad2312..80a32c3 100644
--- a/runtime/tests/vm/dart/disassemble_aot_test.dart
+++ b/runtime/tests/vm/dart/disassemble_aot_test.dart
@@ -1,8 +1,11 @@
 // 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.
-
+//
+// OtherResources=use_dwarf_stack_traces_flag_program.dart
+//
 // Tests proper object recognition in disassembler.
+
 import 'dart:async';
 import 'dart:io';
 
@@ -12,25 +15,41 @@
 import 'use_flag_test_helper.dart';
 
 Future<void> main(List<String> args) async {
-  if (Platform.isAndroid) {
-    return; // SDK tree and gen_snapshot not available on the test device.
+  if (!isAOTRuntime) {
+    return; // Running in JIT: AOT binaries not available.
   }
 
-  final buildDir = path.dirname(Platform.executable);
-  final sdkDir = path.dirname(path.dirname(buildDir));
-  final platformDill = path.join(buildDir, 'vm_platform_strong.dill');
-  final genSnapshot = path.join(buildDir, 'gen_snapshot');
+  if (const bool.fromEnvironment('dart.vm.product')) {
+    return; // No disassembling in PRODUCT mode.
+  }
+
+  if (Platform.isAndroid) {
+    return; // SDK tree and dart_bootstrap not available on the test device.
+  }
+
+  // These are the tools we need to be available to run on a given platform:
+  if (!await testExecutable(genSnapshot)) {
+    throw "Cannot run test as $genSnapshot not available";
+  }
+  if (!await testExecutable(aotRuntime)) {
+    throw "Cannot run test as $aotRuntime not available";
+  }
+  if (!File(platformDill).existsSync()) {
+    throw "Cannot run test as $platformDill does not exist";
+  }
 
   await withTempDir('disassemble_aot', (String tempDir) async {
+    final cwDir = path.dirname(Platform.script.toFilePath());
+    final script = path.join(cwDir, 'use_dwarf_stack_traces_flag_program.dart');
     final scriptDill = path.join(tempDir, 'out.dill');
 
     // Compile script to Kernel IR.
-    await run('pkg/vm/tool/gen_kernel', <String>[
+    await run(genKernel, <String>[
       '--aot',
       '--platform=$platformDill',
       '-o',
       scriptDill,
-      Platform.script.toString(),
+      script,
     ]);
 
     // Run the AOT compiler with the disassemble flags set.
diff --git a/runtime/tests/vm/dart/regress_flutter83094_test.dart b/runtime/tests/vm/dart/regress_flutter83094_test.dart
new file mode 100644
index 0000000..2572019
--- /dev/null
+++ b/runtime/tests/vm/dart/regress_flutter83094_test.dart
@@ -0,0 +1,27 @@
+// 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.
+
+// Verifies that compiler doesn't crash due to incompatible types
+// when unboxing input of a Phi.
+// Regression test for https://github.com/flutter/flutter/issues/83094.
+
+import 'package:expect/expect.dart';
+
+class A {
+  @pragma('vm:never-inline')
+  double getMaxIntrinsicWidth() => 1.toDouble();
+}
+
+A _leading = A();
+
+@pragma('vm:never-inline')
+double computeMaxIntrinsicWidth(double height, double horizontalPadding) {
+  final leadingWidth =
+      _leading == null ? 0 : _leading.getMaxIntrinsicWidth() as int;
+  return horizontalPadding + leadingWidth;
+}
+
+main() {
+  Expect.throws(() => computeMaxIntrinsicWidth(1, 2));
+}
diff --git a/runtime/tests/vm/dart_2/disassemble_aot_test.dart b/runtime/tests/vm/dart_2/disassemble_aot_test.dart
index 1ad2312..80a32c3 100644
--- a/runtime/tests/vm/dart_2/disassemble_aot_test.dart
+++ b/runtime/tests/vm/dart_2/disassemble_aot_test.dart
@@ -1,8 +1,11 @@
 // 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.
-
+//
+// OtherResources=use_dwarf_stack_traces_flag_program.dart
+//
 // Tests proper object recognition in disassembler.
+
 import 'dart:async';
 import 'dart:io';
 
@@ -12,25 +15,41 @@
 import 'use_flag_test_helper.dart';
 
 Future<void> main(List<String> args) async {
-  if (Platform.isAndroid) {
-    return; // SDK tree and gen_snapshot not available on the test device.
+  if (!isAOTRuntime) {
+    return; // Running in JIT: AOT binaries not available.
   }
 
-  final buildDir = path.dirname(Platform.executable);
-  final sdkDir = path.dirname(path.dirname(buildDir));
-  final platformDill = path.join(buildDir, 'vm_platform_strong.dill');
-  final genSnapshot = path.join(buildDir, 'gen_snapshot');
+  if (const bool.fromEnvironment('dart.vm.product')) {
+    return; // No disassembling in PRODUCT mode.
+  }
+
+  if (Platform.isAndroid) {
+    return; // SDK tree and dart_bootstrap not available on the test device.
+  }
+
+  // These are the tools we need to be available to run on a given platform:
+  if (!await testExecutable(genSnapshot)) {
+    throw "Cannot run test as $genSnapshot not available";
+  }
+  if (!await testExecutable(aotRuntime)) {
+    throw "Cannot run test as $aotRuntime not available";
+  }
+  if (!File(platformDill).existsSync()) {
+    throw "Cannot run test as $platformDill does not exist";
+  }
 
   await withTempDir('disassemble_aot', (String tempDir) async {
+    final cwDir = path.dirname(Platform.script.toFilePath());
+    final script = path.join(cwDir, 'use_dwarf_stack_traces_flag_program.dart');
     final scriptDill = path.join(tempDir, 'out.dill');
 
     // Compile script to Kernel IR.
-    await run('pkg/vm/tool/gen_kernel', <String>[
+    await run(genKernel, <String>[
       '--aot',
       '--platform=$platformDill',
       '-o',
       scriptDill,
-      Platform.script.toString(),
+      script,
     ]);
 
     // Run the AOT compiler with the disassemble flags set.
diff --git a/runtime/tests/vm/dart_2/regress_flutter83094_test.dart b/runtime/tests/vm/dart_2/regress_flutter83094_test.dart
new file mode 100644
index 0000000..2572019
--- /dev/null
+++ b/runtime/tests/vm/dart_2/regress_flutter83094_test.dart
@@ -0,0 +1,27 @@
+// 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.
+
+// Verifies that compiler doesn't crash due to incompatible types
+// when unboxing input of a Phi.
+// Regression test for https://github.com/flutter/flutter/issues/83094.
+
+import 'package:expect/expect.dart';
+
+class A {
+  @pragma('vm:never-inline')
+  double getMaxIntrinsicWidth() => 1.toDouble();
+}
+
+A _leading = A();
+
+@pragma('vm:never-inline')
+double computeMaxIntrinsicWidth(double height, double horizontalPadding) {
+  final leadingWidth =
+      _leading == null ? 0 : _leading.getMaxIntrinsicWidth() as int;
+  return horizontalPadding + leadingWidth;
+}
+
+main() {
+  Expect.throws(() => computeMaxIntrinsicWidth(1, 2));
+}
diff --git a/runtime/vm/compiler/backend/flow_graph.cc b/runtime/vm/compiler/backend/flow_graph.cc
index a24af44..52c25a2 100644
--- a/runtime/vm/compiler/backend/flow_graph.cc
+++ b/runtime/vm/compiler/backend/flow_graph.cc
@@ -1869,7 +1869,6 @@
                                  bool is_environment_use) {
   ASSERT(from != to);
   Instruction* insert_before;
-  Instruction* deopt_target;
   PhiInstr* phi = use->instruction()->AsPhi();
   if (phi != NULL) {
     ASSERT(phi->is_alive());
@@ -1877,14 +1876,19 @@
     auto predecessor = phi->block()->PredecessorAt(use->use_index());
     insert_before = predecessor->last_instruction();
     ASSERT(insert_before->GetBlock() == predecessor);
-    deopt_target = NULL;
   } else {
-    deopt_target = insert_before = use->instruction();
+    insert_before = use->instruction();
+  }
+  const Instruction::SpeculativeMode speculative_mode =
+      use->instruction()->SpeculativeModeOfInput(use->use_index());
+  Instruction* deopt_target = nullptr;
+  if (speculative_mode == Instruction::kGuardInputs || to == kUnboxedInt32) {
+    deopt_target = insert_before;
   }
 
   Definition* converted = NULL;
   if (IsUnboxedInteger(from) && IsUnboxedInteger(to)) {
-    const intptr_t deopt_id = (to == kUnboxedInt32) && (deopt_target != NULL)
+    const intptr_t deopt_id = (to == kUnboxedInt32) && (deopt_target != nullptr)
                                   ? deopt_target->DeoptimizationTarget()
                                   : DeoptId::kNone;
     converted =
@@ -1893,18 +1897,17 @@
     converted = new Int32ToDoubleInstr(use->CopyWithType());
   } else if ((from == kUnboxedInt64) && (to == kUnboxedDouble) &&
              CanConvertInt64ToDouble()) {
-    const intptr_t deopt_id = (deopt_target != NULL)
+    const intptr_t deopt_id = (deopt_target != nullptr)
                                   ? deopt_target->DeoptimizationTarget()
                                   : DeoptId::kNone;
     ASSERT(CanUnboxDouble());
     converted = new Int64ToDoubleInstr(use->CopyWithType(), deopt_id);
   } else if ((from == kTagged) && Boxing::Supports(to)) {
-    const intptr_t deopt_id = (deopt_target != NULL)
+    const intptr_t deopt_id = (deopt_target != nullptr)
                                   ? deopt_target->DeoptimizationTarget()
                                   : DeoptId::kNone;
-    converted = UnboxInstr::Create(
-        to, use->CopyWithType(), deopt_id,
-        use->instruction()->SpeculativeModeOfInput(use->use_index()));
+    converted =
+        UnboxInstr::Create(to, use->CopyWithType(), deopt_id, speculative_mode);
   } else if ((to == kTagged) && Boxing::Supports(from)) {
     converted = BoxInstr::Create(from, use->CopyWithType());
   } else {
@@ -1912,30 +1915,32 @@
     // Insert two "dummy" conversion instructions with the correct
     // "from" and "to" representation. The inserted instructions will
     // trigger a deoptimization if executed. See #12417 for a discussion.
-    const intptr_t deopt_id = (deopt_target != NULL)
+    // If the use is not speculative, then this code should be unreachable.
+    // Insert Stop for a graceful error and aid unreachable code elimination.
+    if (speculative_mode == Instruction::kNotSpeculative) {
+      StopInstr* stop = new (Z) StopInstr("Incompatible conversion.");
+      InsertBefore(insert_before, stop, nullptr, FlowGraph::kEffect);
+    }
+    const intptr_t deopt_id = (deopt_target != nullptr)
                                   ? deopt_target->DeoptimizationTarget()
                                   : DeoptId::kNone;
     ASSERT(Boxing::Supports(from));
     ASSERT(Boxing::Supports(to));
     Definition* boxed = BoxInstr::Create(from, use->CopyWithType());
     use->BindTo(boxed);
-    InsertBefore(insert_before, boxed, NULL, FlowGraph::kValue);
-    converted = UnboxInstr::Create(to, new (Z) Value(boxed), deopt_id);
+    InsertBefore(insert_before, boxed, nullptr, FlowGraph::kValue);
+    converted = UnboxInstr::Create(to, new (Z) Value(boxed), deopt_id,
+                                   speculative_mode);
   }
-  ASSERT(converted != NULL);
-  InsertBefore(insert_before, converted, use->instruction()->env(),
+  ASSERT(converted != nullptr);
+  InsertBefore(insert_before, converted,
+               (deopt_target != nullptr) ? deopt_target->env() : nullptr,
                FlowGraph::kValue);
   if (is_environment_use) {
     use->BindToEnvironment(converted);
   } else {
     use->BindTo(converted);
   }
-
-  if ((to == kUnboxedInt32) && (phi != NULL)) {
-    // Int32 phis are unboxed optimistically. Ensure that unboxing
-    // has deoptimization target attached from the goto instruction.
-    CopyDeoptTarget(converted, insert_before);
-  }
 }
 
 void FlowGraph::InsertConversionsFor(Definition* def) {
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index a53501e..823d9da 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -2481,9 +2481,12 @@
 
   virtual void set_representation(Representation r) { representation_ = r; }
 
-  // In AOT mode Phi instructions do not check types of inputs when unboxing.
+  // Only Int32 phis in JIT mode are unboxed optimistically.
   virtual SpeculativeMode SpeculativeModeOfInput(intptr_t index) const {
-    return CompilerState::Current().is_aot() ? kNotSpeculative : kGuardInputs;
+    return (CompilerState::Current().is_aot() ||
+            (representation_ != kUnboxedInt32))
+               ? kNotSpeculative
+               : kGuardInputs;
   }
 
   virtual uword Hash() const {
@@ -3140,6 +3143,9 @@
     return true;
   }
 
+  // May require a deoptimization target for int32 Phi input conversions.
+  virtual intptr_t DeoptimizationTarget() const { return GetDeoptId(); }
+
   virtual bool ComputeCanDeoptimize() const { return false; }
 
   virtual bool HasUnknownSideEffects() const { return false; }
@@ -4097,6 +4103,7 @@
       }
       idx--;
     }
+    if (interface_target_.IsNull()) return kGuardInputs;
     return interface_target_.is_unboxed_parameter_at(idx) ? kNotSpeculative
                                                           : kGuardInputs;
   }
diff --git a/runtime/vm/compiler/ffi/native_calling_convention.cc b/runtime/vm/compiler/ffi/native_calling_convention.cc
index 79d127a..8312871 100644
--- a/runtime/vm/compiler/ffi/native_calling_convention.cc
+++ b/runtime/vm/compiler/ffi/native_calling_convention.cc
@@ -716,6 +716,11 @@
     max_height_in_bytes = Utils::Maximum(
         max_height_in_bytes, argument_locations_[i]->StackTopInBytes());
   }
+  if (return_location_.IsPointerToMemory()) {
+    const auto& ret_loc = return_location_.AsPointerToMemory();
+    max_height_in_bytes =
+        Utils::Maximum(max_height_in_bytes, ret_loc.StackTopInBytes());
+  }
   return Utils::RoundUp(max_height_in_bytes, compiler::target::kWordSize);
 }
 
diff --git a/runtime/vm/compiler/ffi/native_calling_convention_test.cc b/runtime/vm/compiler/ffi/native_calling_convention_test.cc
index 9d4b672..e9308b9 100644
--- a/runtime/vm/compiler/ffi/native_calling_convention_test.cc
+++ b/runtime/vm/compiler/ffi/native_calling_convention_test.cc
@@ -11,10 +11,11 @@
 namespace compiler {
 namespace ffi {
 
-void RunSignatureTest(dart::Zone* zone,
-                      const char* name,
-                      const NativeTypes& argument_types,
-                      const NativeType& return_type) {
+const NativeCallingConvention& RunSignatureTest(
+    dart::Zone* zone,
+    const char* name,
+    const NativeTypes& argument_types,
+    const NativeType& return_type) {
   const auto& native_signature =
       *new (zone) NativeFunctionType(argument_types, return_type);
 
@@ -42,6 +43,8 @@
     EXPECT_STREQ(expectation_file_contents, test_result);
     free(expectation_file_contents);
   }
+
+  return native_calling_convention;
 }
 
 UNIT_TEST_CASE_WITH_ZONE(NativeCallingConvention_int8x10) {
@@ -555,6 +558,32 @@
   RunSignatureTest(Z, "union5bytesPackedx10", arguments, union_type);
 }
 
+// http://dartbug.com/46127
+//
+// See the *.expect in ./unit_tests for this behavior.
+UNIT_TEST_CASE_WITH_ZONE(NativeCallingConvention_regress46127) {
+  const auto& uint64_type = *new (Z) NativePrimitiveType(kUint64);
+
+  auto& member_types = *new (Z) NativeTypes(Z, 1);
+  member_types.Add(&uint64_type);
+  const auto& struct_type = NativeStructType::FromNativeTypes(Z, member_types);
+
+  EXPECT_EQ(8, struct_type.SizeInBytes());
+
+  auto& arguments = *new (Z) NativeTypes(Z, 0);
+
+  const auto& native_calling_convention =
+      RunSignatureTest(Z, "regress46127", arguments, struct_type);
+
+#if defined(TARGET_ARCH_IA32) &&                                               \
+    (defined(TARGET_OS_ANDROID) || defined(TARGET_OS_LINUX))
+  // We must count the result pointer passed on the stack as well.
+  EXPECT_EQ(4, native_calling_convention.StackTopInBytes());
+#else
+  EXPECT_EQ(0, native_calling_convention.StackTopInBytes());
+#endif
+}
+
 }  // namespace ffi
 }  // namespace compiler
 }  // namespace dart
diff --git a/runtime/vm/compiler/ffi/unit_tests/regress46127/arm64_android.expect b/runtime/vm/compiler/ffi/unit_tests/regress46127/arm64_android.expect
new file mode 100644
index 0000000..9245d0d
--- /dev/null
+++ b/runtime/vm/compiler/ffi/unit_tests/regress46127/arm64_android.expect
@@ -0,0 +1,3 @@
+
+=>
+M(r0 int64) Struct(size: 8)
diff --git a/runtime/vm/compiler/ffi/unit_tests/regress46127/arm64_ios.expect b/runtime/vm/compiler/ffi/unit_tests/regress46127/arm64_ios.expect
new file mode 100644
index 0000000..9245d0d
--- /dev/null
+++ b/runtime/vm/compiler/ffi/unit_tests/regress46127/arm64_ios.expect
@@ -0,0 +1,3 @@
+
+=>
+M(r0 int64) Struct(size: 8)
diff --git a/runtime/vm/compiler/ffi/unit_tests/regress46127/arm64_linux.expect b/runtime/vm/compiler/ffi/unit_tests/regress46127/arm64_linux.expect
new file mode 100644
index 0000000..9245d0d
--- /dev/null
+++ b/runtime/vm/compiler/ffi/unit_tests/regress46127/arm64_linux.expect
@@ -0,0 +1,3 @@
+
+=>
+M(r0 int64) Struct(size: 8)
diff --git a/runtime/vm/compiler/ffi/unit_tests/regress46127/arm64_macos.expect b/runtime/vm/compiler/ffi/unit_tests/regress46127/arm64_macos.expect
new file mode 100644
index 0000000..9245d0d
--- /dev/null
+++ b/runtime/vm/compiler/ffi/unit_tests/regress46127/arm64_macos.expect
@@ -0,0 +1,3 @@
+
+=>
+M(r0 int64) Struct(size: 8)
diff --git a/runtime/vm/compiler/ffi/unit_tests/regress46127/arm_android.expect b/runtime/vm/compiler/ffi/unit_tests/regress46127/arm_android.expect
new file mode 100644
index 0000000..68c5bf6
--- /dev/null
+++ b/runtime/vm/compiler/ffi/unit_tests/regress46127/arm_android.expect
@@ -0,0 +1,3 @@
+
+=>
+P(r0 uint32) Struct(size: 8)
diff --git a/runtime/vm/compiler/ffi/unit_tests/regress46127/arm_ios.expect b/runtime/vm/compiler/ffi/unit_tests/regress46127/arm_ios.expect
new file mode 100644
index 0000000..68c5bf6
--- /dev/null
+++ b/runtime/vm/compiler/ffi/unit_tests/regress46127/arm_ios.expect
@@ -0,0 +1,3 @@
+
+=>
+P(r0 uint32) Struct(size: 8)
diff --git a/runtime/vm/compiler/ffi/unit_tests/regress46127/arm_linux.expect b/runtime/vm/compiler/ffi/unit_tests/regress46127/arm_linux.expect
new file mode 100644
index 0000000..68c5bf6
--- /dev/null
+++ b/runtime/vm/compiler/ffi/unit_tests/regress46127/arm_linux.expect
@@ -0,0 +1,3 @@
+
+=>
+P(r0 uint32) Struct(size: 8)
diff --git a/runtime/vm/compiler/ffi/unit_tests/regress46127/ia32_android.expect b/runtime/vm/compiler/ffi/unit_tests/regress46127/ia32_android.expect
new file mode 100644
index 0000000..2a92c9f
--- /dev/null
+++ b/runtime/vm/compiler/ffi/unit_tests/regress46127/ia32_android.expect
@@ -0,0 +1,3 @@
+
+=>
+P(S+0 uint32, ret:eax uint32) Struct(size: 8)
diff --git a/runtime/vm/compiler/ffi/unit_tests/regress46127/ia32_linux.expect b/runtime/vm/compiler/ffi/unit_tests/regress46127/ia32_linux.expect
new file mode 100644
index 0000000..2a92c9f
--- /dev/null
+++ b/runtime/vm/compiler/ffi/unit_tests/regress46127/ia32_linux.expect
@@ -0,0 +1,3 @@
+
+=>
+P(S+0 uint32, ret:eax uint32) Struct(size: 8)
diff --git a/runtime/vm/compiler/ffi/unit_tests/regress46127/ia32_win.expect b/runtime/vm/compiler/ffi/unit_tests/regress46127/ia32_win.expect
new file mode 100644
index 0000000..22de023
--- /dev/null
+++ b/runtime/vm/compiler/ffi/unit_tests/regress46127/ia32_win.expect
@@ -0,0 +1,3 @@
+
+=>
+M(eax uint32, edx uint32) Struct(size: 8)
diff --git a/runtime/vm/compiler/ffi/unit_tests/regress46127/x64_ios.expect b/runtime/vm/compiler/ffi/unit_tests/regress46127/x64_ios.expect
new file mode 100644
index 0000000..49ae1fd
--- /dev/null
+++ b/runtime/vm/compiler/ffi/unit_tests/regress46127/x64_ios.expect
@@ -0,0 +1,3 @@
+
+=>
+M(rax int64) Struct(size: 8)
diff --git a/runtime/vm/compiler/ffi/unit_tests/regress46127/x64_linux.expect b/runtime/vm/compiler/ffi/unit_tests/regress46127/x64_linux.expect
new file mode 100644
index 0000000..49ae1fd
--- /dev/null
+++ b/runtime/vm/compiler/ffi/unit_tests/regress46127/x64_linux.expect
@@ -0,0 +1,3 @@
+
+=>
+M(rax int64) Struct(size: 8)
diff --git a/runtime/vm/compiler/ffi/unit_tests/regress46127/x64_macos.expect b/runtime/vm/compiler/ffi/unit_tests/regress46127/x64_macos.expect
new file mode 100644
index 0000000..49ae1fd
--- /dev/null
+++ b/runtime/vm/compiler/ffi/unit_tests/regress46127/x64_macos.expect
@@ -0,0 +1,3 @@
+
+=>
+M(rax int64) Struct(size: 8)
diff --git a/runtime/vm/compiler/ffi/unit_tests/regress46127/x64_win.expect b/runtime/vm/compiler/ffi/unit_tests/regress46127/x64_win.expect
new file mode 100644
index 0000000..49ae1fd
--- /dev/null
+++ b/runtime/vm/compiler/ffi/unit_tests/regress46127/x64_win.expect
@@ -0,0 +1,3 @@
+
+=>
+M(rax int64) Struct(size: 8)
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 0b91d37..bb3fea0 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -921,6 +921,7 @@
   const intptr_t field_id = field.field_id();
   initial_field_table()->SetAt(field_id, initial_value.ptr());
 
+  SafepointReadRwLocker ml(Thread::Current(), isolates_lock_.get());
   if (need_to_grow_backing_store) {
     // We have to stop other isolates from accessing their field state, since
     // we'll have to grow the backing store.
diff --git a/tests/ffi/regress_46127_test.dart b/tests/ffi/regress_46127_test.dart
new file mode 100644
index 0000000..4a60c59
--- /dev/null
+++ b/tests/ffi/regress_46127_test.dart
@@ -0,0 +1,25 @@
+// 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.
+//
+// SharedObjects=ffi_test_functions
+
+import 'dart:ffi';
+
+import "package:expect/expect.dart";
+
+import 'dylib_utils.dart';
+
+final nativeLib = dlopenPlatformSpecific("ffi_test_functions");
+
+class Struct46127 extends Struct {
+  @Uint64()
+  external int val;
+}
+
+void main() {
+  final struct =
+      nativeLib.lookupFunction<Struct46127 Function(), Struct46127 Function()>(
+          'Regress46127')();
+  Expect.equals(123, struct.val);
+}
diff --git a/tests/ffi_2/regress_46127_test.dart b/tests/ffi_2/regress_46127_test.dart
new file mode 100644
index 0000000..73d9f61
--- /dev/null
+++ b/tests/ffi_2/regress_46127_test.dart
@@ -0,0 +1,25 @@
+// 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.
+//
+// SharedObjects=ffi_test_functions
+
+import 'dart:ffi';
+
+import "package:expect/expect.dart";
+
+import 'dylib_utils.dart';
+
+final nativeLib = dlopenPlatformSpecific("ffi_test_functions");
+
+class Struct46127 extends Struct {
+  @Uint64()
+  int val;
+}
+
+void main() {
+  final struct =
+      nativeLib.lookupFunction<Struct46127 Function(), Struct46127 Function()>(
+          'Regress46127')();
+  Expect.equals(123, struct.val);
+}
diff --git a/tools/VERSION b/tools/VERSION
index 9e0a3a9..33b98db 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 14
 PATCH 0
-PRERELEASE 156
+PRERELEASE 157
 PRERELEASE_PATCH 0
\ No newline at end of file