diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc index 3d38bf71c2f..0f193da3de0 100644 --- a/runtime/vm/compiler/frontend/kernel_to_il.cc +++ b/runtime/vm/compiler/frontend/kernel_to_il.cc @@ -1332,6 +1332,16 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfRecognizedMethod( body += FloatToDouble(); } body += Box(kUnboxedDouble); + } else if (kind == MethodRecognizer::kFfiLoadInt8 || + kind == MethodRecognizer::kFfiLoadInt16 || + kind == MethodRecognizer::kFfiLoadUint8 || + kind == MethodRecognizer::kFfiLoadUint16) { + // LoadIndexed instruction with 8-bit and 16-bit elements + // results in value with kUnboxedIntPtr representation + // (see LoadIndexedInstr::representation). + // Avoid any unnecessary (and potentially deoptimizing) int + // conversions by using the correct representation at the first place. + body += Box(kUnboxedIntPtr); } else { body += Box(native_rep.AsRepresentationOverApprox(zone_)); if (kind == MethodRecognizer::kFfiLoadPointer) { @@ -1462,6 +1472,16 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfRecognizedMethod( kind == MethodRecognizer::kFfiStoreFloatUnaligned) { body += DoubleToFloat(); } + } else if (kind == MethodRecognizer::kFfiStoreInt8 || + kind == MethodRecognizer::kFfiStoreInt16 || + kind == MethodRecognizer::kFfiStoreUint8 || + kind == MethodRecognizer::kFfiStoreUint16) { + // StoreIndexed instruction with 8-bit and 16-bit elements + // takes value with kUnboxedIntPtr representation + // (see StoreIndexedInstr::RequiredInputRepresentation). + // Avoid any unnecessary (and potentially deoptimizing) int + // conversions by using the correct representation at the first place. + body += UnboxTruncate(kUnboxedIntPtr); } else { body += UnboxTruncate(native_rep.AsRepresentationOverApprox(zone_)); } diff --git a/tests/ffi/regress_flutter79441_test.dart b/tests/ffi/regress_flutter79441_test.dart new file mode 100644 index 00000000000..7f1336fdfe0 --- /dev/null +++ b/tests/ffi/regress_flutter79441_test.dart @@ -0,0 +1,38 @@ +// 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. + +// Regression test for https://github.com/flutter/flutter/issues/79441. + +import 'dart:ffi'; + +// FFI signature +typedef _dart_memset = void Function(Pointer, int, int); +typedef _c_memset = Void Function(Pointer, Int32, IntPtr); + +_dart_memset? fbMemset; + +void _fallbackMemset(Pointer ptr, int byte, int size) { + final bytes = ptr.cast(); + for (var i = 0; i < size; i++) { + bytes[i] = byte; + } +} + +void main() { + try { + fbMemset = DynamicLibrary.process() + .lookupFunction<_c_memset, _dart_memset>('memset'); + } catch (_) { + // This works: + // fbMemset = _fallbackMemset; + + // This doesn't: /aot/precompiler.cc: 2761: error: unreachable code + fbMemset = (Pointer ptr, int byte, int size) { + final bytes = ptr.cast(); + for (var i = 0; i < size; i++) { + bytes[i] = byte; + } + }; + } +} diff --git a/tests/ffi_2/regress_flutter79441_test.dart b/tests/ffi_2/regress_flutter79441_test.dart new file mode 100644 index 00000000000..a9b17de0b57 --- /dev/null +++ b/tests/ffi_2/regress_flutter79441_test.dart @@ -0,0 +1,38 @@ +// 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. + +// Regression test for https://github.com/flutter/flutter/issues/79441. + +import 'dart:ffi'; + +// FFI signature +typedef _dart_memset = void Function(Pointer, int, int); +typedef _c_memset = Void Function(Pointer, Int32, IntPtr); + +_dart_memset fbMemset; + +void _fallbackMemset(Pointer ptr, int byte, int size) { + final bytes = ptr.cast(); + for (var i = 0; i < size; i++) { + bytes[i] = byte; + } +} + +void main() { + try { + fbMemset = DynamicLibrary.process() + .lookupFunction<_c_memset, _dart_memset>('memset'); + } catch (_) { + // This works: + // fbMemset = _fallbackMemset; + + // This doesn't: /aot/precompiler.cc: 2761: error: unreachable code + fbMemset = (Pointer ptr, int byte, int size) { + final bytes = ptr.cast(); + for (var i = 0; i < size; i++) { + bytes[i] = byte; + } + }; + } +}