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