From 9e16846bf93ea58ef564cdefae8835ac27cd248e Mon Sep 17 00:00:00 2001 From: Alexander Markov Date: Tue, 1 Feb 2022 16:49:56 +0000 Subject: [PATCH] [vm/compiler] Avoid speculative conversion in ffi Pointer.asTypedList On 32-bit ARM in AOT mode Pointer.asTypedList is generated so that there is a LoadField from Pointer.data_field which has kUnboxedFfiIntPtr representation (uint32) and then the value is passed to a StoreInstanceField for TypedDataBase.data_field which has kUnboxedIntPtr representation (int32). As a result, a speculative uint32->int32 IntConverter instruction is inserted by SelectRepresentations pass. AOT doesn't support deoptimization so code generation crashes after retrying without speculative inlining. This change fixes the type incompatibility by loading value with LoadUntagged and then converting it with ConvertUntaggedToUnboxed(kUnboxedIntPtr). TEST=ffi/regress_flutter97301_test Fixes https://github.com/flutter/flutter/issues/97301 Change-Id: I4a00d4ac7978b4775add0ddae510841a2b4cbae0 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/230956 Reviewed-by: Daco Harkes Reviewed-by: Martin Kustermann Commit-Queue: Alexander Markov --- runtime/vm/compiler/frontend/kernel_to_il.cc | 3 ++- tests/ffi/regress_flutter97301_test.dart | 21 ++++++++++++++++++ tests/ffi_2/regress_flutter97301_test.dart | 23 ++++++++++++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 tests/ffi/regress_flutter97301_test.dart create mode 100644 tests/ffi_2/regress_flutter97301_test.dart diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc index 08ff0cc3a9e4..5147fdc7edf1 100644 --- a/runtime/vm/compiler/frontend/kernel_to_il.cc +++ b/runtime/vm/compiler/frontend/kernel_to_il.cc @@ -1582,7 +1582,8 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfRecognizedMethod( // Initialize the result's data pointer field. body += LoadLocal(typed_data_object); body += LoadLocal(arg_pointer); - body += LoadNativeField(Slot::Pointer_data_field()); + body += LoadUntagged(compiler::target::Pointer::data_field_offset()); + body += ConvertUntaggedToUnboxed(kUnboxedIntPtr); body += StoreNativeField(Slot::TypedDataBase_data_field(), StoreInstanceFieldInstr::Kind::kInitializing, kNoStoreBarrier); diff --git a/tests/ffi/regress_flutter97301_test.dart b/tests/ffi/regress_flutter97301_test.dart new file mode 100644 index 000000000000..c330d70ff151 --- /dev/null +++ b/tests/ffi/regress_flutter97301_test.dart @@ -0,0 +1,21 @@ +// Copyright (c) 2022, 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 there are no deoptimizing IntConverter instructions +// used when converting Pointer to TypedData. +// Regression test for https://github.com/flutter/flutter/issues/97301. + +import "dart:ffi"; +import "package:ffi/ffi.dart"; + +@pragma("vm:never-inline") +Pointer foo() => calloc(4); + +main() { + final Pointer offsetsPtr = foo(); + + for (var i = 0; i < 2; i++) { + print(offsetsPtr.asTypedList(1)); + } +} diff --git a/tests/ffi_2/regress_flutter97301_test.dart b/tests/ffi_2/regress_flutter97301_test.dart new file mode 100644 index 000000000000..1417a7a29f93 --- /dev/null +++ b/tests/ffi_2/regress_flutter97301_test.dart @@ -0,0 +1,23 @@ +// Copyright (c) 2022, 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 there are no deoptimizing IntConverter instructions +// used when converting Pointer to TypedData. +// Regression test for https://github.com/flutter/flutter/issues/97301. + +// @dart = 2.9 + +import "dart:ffi"; +import "package:ffi/ffi.dart"; + +@pragma("vm:never-inline") +Pointer foo() => calloc(4); + +main() { + final Pointer offsetsPtr = foo(); + + for (var i = 0; i < 2; i++) { + print(offsetsPtr.asTypedList(1)); + } +}