From fca959e5f67f0e2ef7bd7c5d42165049df04d3cf Mon Sep 17 00:00:00 2001 From: Daco Harkes Date: Thu, 11 Feb 2021 18:09:05 +0000 Subject: [PATCH] [vm/ffi] Add class to `vm:ffi:struct-fields` pragma This CL changes `@pragma('vm:ffi:struct-fields', [...])` to `@pragma('vm:ffi:struct-fields', _FfiStructLayout([...]))` which makes it easier to add more data in subsequent CLs. Extends `FindPragma` to allow returning multiple matched pragma's, so that we can filter them. (In this case to avoid matching user-defined pragma's that do not have an instance of the private class.) Separated out from https://dart-review.googlesource.com/c/sdk/+/183640 because of the extra constant in existing expectation files. Bug: https://github.com/dart-lang/sdk/issues/35763 Bug: https://github.com/dart-lang/sdk/issues/38158 TEST=tests/ffi(_2)/*_by_value_*_test.dart Change-Id: Idef9f82e9b53c2a32dffabcec19669eae550fe2f Cq-Include-Trybots: luci.dart.try:front-end-nnbd-mac-release-x64-try,front-end-linux-release-x64-try,vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-nnbd-linux-debug-x64-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/184181 Reviewed-by: Martin Kustermann Reviewed-by: Clement Skau --- .../general_nnbd_opt_out/ffi_sample.dart | 2 +- .../ffi_sample.dart.weak.transformed.expect | 37 ++++++------- .../ffi_01.yaml.world.1.expect | 37 ++++++------- .../ffi_01.yaml.world.2.expect | 37 ++++++------- .../ffi_02.yaml.world.1.expect | 37 ++++++------- .../no_outline_change_35.yaml.world.1.expect | 37 ++++++------- .../no_outline_change_35.yaml.world.2.expect | 37 ++++++------- .../no_outline_change_35.yaml.world.3.expect | 37 ++++++------- .../ffi_sample.dart.strong.transformed.expect | 47 ++++++++-------- .../ffi_sample.dart.weak.transformed.expect | 47 ++++++++-------- pkg/vm/lib/transformations/ffi.dart | 5 ++ .../lib/transformations/ffi_definitions.dart | 11 ++-- runtime/vm/compiler/backend/inliner.cc | 7 +-- .../backend/redundancy_elimination.cc | 3 +- .../compiler/backend/type_propagator_test.cc | 2 +- runtime/vm/compiler/ffi/native_type.cc | 54 +++++++++++++++---- .../frontend/base_flow_graph_builder.cc | 3 +- runtime/vm/compiler/method_recognizer.cc | 12 +++-- runtime/vm/object.cc | 21 +++++++- runtime/vm/object.h | 12 +++-- runtime/vm/symbols.h | 2 + .../_internal/vm/lib/ffi_struct_patch.dart | 8 +++ 22 files changed, 290 insertions(+), 205 deletions(-) diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/ffi_sample.dart b/pkg/front_end/testcases/general_nnbd_opt_out/ffi_sample.dart index a4246748ba89..b1986695fb75 100644 --- a/pkg/front_end/testcases/general_nnbd_opt_out/ffi_sample.dart +++ b/pkg/front_end/testcases/general_nnbd_opt_out/ffi_sample.dart @@ -20,7 +20,7 @@ class Coordinate extends Struct { Pointer next; - factory Coordinate.allocate( + factory Coordinate.allocate( Allocator allocator, double x, double y, Pointer next) { return allocator().ref ..x = x diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/ffi_sample.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/ffi_sample.dart.weak.transformed.expect index 94630fcc032e..8c4ed968d4a9 100644 --- a/pkg/front_end/testcases/general_nnbd_opt_out/ffi_sample.dart.weak.transformed.expect +++ b/pkg/front_end/testcases/general_nnbd_opt_out/ffi_sample.dart.weak.transformed.expect @@ -12,10 +12,10 @@ import "dart:ffi"; import "package:ffi/ffi.dart"; @#C3 -@#C8 +@#C9 class Coordinate extends ffi::Struct { @#C3 - static final field core::int* #sizeOf = (#C11).{core::List::[]}(ffi::_abi()); + static final field core::int* #sizeOf = (#C12).{core::List::[]}(ffi::_abi()); @#C3 constructor #fromTypedDataBase(dynamic #pointer) → dynamic : super ffi::Struct::_fromPointer(#pointer) @@ -39,17 +39,17 @@ class Coordinate extends ffi::Struct { abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType get x() → core::double* - return ffi::_loadDouble(this.{ffi::Struct::_addressOf}, (#C13).{core::List::[]}(ffi::_abi())); + return ffi::_loadDouble(this.{ffi::Struct::_addressOf}, (#C14).{core::List::[]}(ffi::_abi())); set x(core::double* #v) → void - return ffi::_storeDouble(this.{ffi::Struct::_addressOf}, (#C13).{core::List::[]}(ffi::_abi()), #v); + return ffi::_storeDouble(this.{ffi::Struct::_addressOf}, (#C14).{core::List::[]}(ffi::_abi()), #v); get y() → core::double* - return ffi::_loadDouble(this.{ffi::Struct::_addressOf}, (#C15).{core::List::[]}(ffi::_abi())); + return ffi::_loadDouble(this.{ffi::Struct::_addressOf}, (#C16).{core::List::[]}(ffi::_abi())); set y(core::double* #v) → void - return ffi::_storeDouble(this.{ffi::Struct::_addressOf}, (#C15).{core::List::[]}(ffi::_abi()), #v); + return ffi::_storeDouble(this.{ffi::Struct::_addressOf}, (#C16).{core::List::[]}(ffi::_abi()), #v); get next() → ffi::Pointer* - return ffi::_fromAddress(ffi::_loadIntPtr(this.{ffi::Struct::_addressOf}, (#C17).{core::List::[]}(ffi::_abi()))); + return ffi::_fromAddress(ffi::_loadIntPtr(this.{ffi::Struct::_addressOf}, (#C18).{core::List::[]}(ffi::_abi()))); set next(ffi::Pointer* #v) → void - return ffi::_storeIntPtr(this.{ffi::Struct::_addressOf}, (#C17).{core::List::[]}(ffi::_abi()), #v.{ffi::Pointer::address}); + return ffi::_storeIntPtr(this.{ffi::Struct::_addressOf}, (#C18).{core::List::[]}(ffi::_abi()), #v.{ffi::Pointer::address}); } static method main() → dynamic {} @@ -61,16 +61,17 @@ constants { #C5 = TypeLiteralConstant(ffi::Double) #C6 = TypeLiteralConstant(ffi::Pointer) #C7 = [#C5, #C5, #C6] - #C8 = core::pragma {name:#C4, options:#C7} - #C9 = 24 - #C10 = 20 - #C11 = [#C9, #C10, #C9] - #C12 = 0 - #C13 = [#C12, #C12, #C12] - #C14 = 8 - #C15 = [#C14, #C14, #C14] - #C16 = 16 - #C17 = [#C16, #C16, #C16] + #C8 = ffi::_FfiStructLayout {fieldTypes:#C7} + #C9 = core::pragma {name:#C4, options:#C8} + #C10 = 24 + #C11 = 20 + #C12 = [#C10, #C11, #C10] + #C13 = 0 + #C14 = [#C13, #C13, #C13] + #C15 = 8 + #C16 = [#C15, #C15, #C15] + #C17 = 16 + #C18 = [#C17, #C17, #C17] } diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/ffi_01.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/ffi_01.yaml.world.1.expect index f93c1a3363e0..08f11e75bc3b 100644 --- a/pkg/front_end/testcases/incremental_initialize_from_dill/ffi_01.yaml.world.1.expect +++ b/pkg/front_end/testcases/incremental_initialize_from_dill/ffi_01.yaml.world.1.expect @@ -4,10 +4,10 @@ library from "org-dartlang-test:///lib.dart" as lib { import "dart:ffi"; @#C3 - @#C8 + @#C9 class Coordinate extends dart.ffi::Struct { @#C3 - static final field dart.core::int* #sizeOf = (#C11).{dart.core::List::[]}(dart.ffi::_abi()); + static final field dart.core::int* #sizeOf = (#C12).{dart.core::List::[]}(dart.ffi::_abi()); @#C3 constructor #fromTypedDataBase(dynamic #pointer) → dynamic : super dart.ffi::Struct::_fromPointer(#pointer) @@ -27,17 +27,17 @@ library from "org-dartlang-test:///lib.dart" as lib { abstract member-signature method noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod abstract member-signature get runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType get x() → dart.core::double* - return dart.ffi::_loadDouble(this.{dart.ffi::Struct::_addressOf}, (#C13).{dart.core::List::[]}(dart.ffi::_abi())); + return dart.ffi::_loadDouble(this.{dart.ffi::Struct::_addressOf}, (#C14).{dart.core::List::[]}(dart.ffi::_abi())); set x(dart.core::double* #v) → void - return dart.ffi::_storeDouble(this.{dart.ffi::Struct::_addressOf}, (#C13).{dart.core::List::[]}(dart.ffi::_abi()), #v); + return dart.ffi::_storeDouble(this.{dart.ffi::Struct::_addressOf}, (#C14).{dart.core::List::[]}(dart.ffi::_abi()), #v); get y() → dart.core::double* - return dart.ffi::_loadDouble(this.{dart.ffi::Struct::_addressOf}, (#C15).{dart.core::List::[]}(dart.ffi::_abi())); + return dart.ffi::_loadDouble(this.{dart.ffi::Struct::_addressOf}, (#C16).{dart.core::List::[]}(dart.ffi::_abi())); set y(dart.core::double* #v) → void - return dart.ffi::_storeDouble(this.{dart.ffi::Struct::_addressOf}, (#C15).{dart.core::List::[]}(dart.ffi::_abi()), #v); + return dart.ffi::_storeDouble(this.{dart.ffi::Struct::_addressOf}, (#C16).{dart.core::List::[]}(dart.ffi::_abi()), #v); get next() → dart.ffi::Pointer* - return dart.ffi::_fromAddress(dart.ffi::_loadIntPtr(this.{dart.ffi::Struct::_addressOf}, (#C17).{dart.core::List::[]}(dart.ffi::_abi()))); + return dart.ffi::_fromAddress(dart.ffi::_loadIntPtr(this.{dart.ffi::Struct::_addressOf}, (#C18).{dart.core::List::[]}(dart.ffi::_abi()))); set next(dart.ffi::Pointer* #v) → void - return dart.ffi::_storeIntPtr(this.{dart.ffi::Struct::_addressOf}, (#C17).{dart.core::List::[]}(dart.ffi::_abi()), #v.{dart.ffi::Pointer::address}); + return dart.ffi::_storeIntPtr(this.{dart.ffi::Struct::_addressOf}, (#C18).{dart.core::List::[]}(dart.ffi::_abi()), #v.{dart.ffi::Pointer::address}); } } library from "org-dartlang-test:///main.dart" as main { @@ -59,14 +59,15 @@ constants { #C5 = TypeLiteralConstant(dart.ffi::Double) #C6 = TypeLiteralConstant(dart.ffi::Pointer) #C7 = [#C5, #C5, #C6] - #C8 = dart.core::pragma {name:#C4, options:#C7} - #C9 = 24 - #C10 = 20 - #C11 = [#C9, #C10, #C9] - #C12 = 0 - #C13 = [#C12, #C12, #C12] - #C14 = 8 - #C15 = [#C14, #C14, #C14] - #C16 = 16 - #C17 = [#C16, #C16, #C16] + #C8 = dart.ffi::_FfiStructLayout {fieldTypes:#C7} + #C9 = dart.core::pragma {name:#C4, options:#C8} + #C10 = 24 + #C11 = 20 + #C12 = [#C10, #C11, #C10] + #C13 = 0 + #C14 = [#C13, #C13, #C13] + #C15 = 8 + #C16 = [#C15, #C15, #C15] + #C17 = 16 + #C18 = [#C17, #C17, #C17] } diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/ffi_01.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/ffi_01.yaml.world.2.expect index 466b63f982c8..77ff6cd77833 100644 --- a/pkg/front_end/testcases/incremental_initialize_from_dill/ffi_01.yaml.world.2.expect +++ b/pkg/front_end/testcases/incremental_initialize_from_dill/ffi_01.yaml.world.2.expect @@ -4,10 +4,10 @@ library from "org-dartlang-test:///lib.dart" as lib { import "dart:ffi"; @#C3 - @#C8 + @#C9 class Coordinate extends dart.ffi::Struct { @#C3 - static final field dart.core::int* #sizeOf = (#C11).{dart.core::List::[]}(dart.ffi::_abi()); + static final field dart.core::int* #sizeOf = (#C12).{dart.core::List::[]}(dart.ffi::_abi()); @#C3 constructor #fromTypedDataBase(dynamic #pointer) → dynamic : super dart.ffi::Struct::_fromPointer(#pointer) @@ -27,17 +27,17 @@ library from "org-dartlang-test:///lib.dart" as lib { abstract member-signature method noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod abstract member-signature get runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType get x() → dart.core::double* - return dart.ffi::_loadDouble(this.{dart.ffi::Struct::_addressOf}, (#C13).{dart.core::List::[]}(dart.ffi::_abi())); + return dart.ffi::_loadDouble(this.{dart.ffi::Struct::_addressOf}, (#C14).{dart.core::List::[]}(dart.ffi::_abi())); set x(dart.core::double* #v) → void - return dart.ffi::_storeDouble(this.{dart.ffi::Struct::_addressOf}, (#C13).{dart.core::List::[]}(dart.ffi::_abi()), #v); + return dart.ffi::_storeDouble(this.{dart.ffi::Struct::_addressOf}, (#C14).{dart.core::List::[]}(dart.ffi::_abi()), #v); get y() → dart.core::double* - return dart.ffi::_loadDouble(this.{dart.ffi::Struct::_addressOf}, (#C15).{dart.core::List::[]}(dart.ffi::_abi())); + return dart.ffi::_loadDouble(this.{dart.ffi::Struct::_addressOf}, (#C16).{dart.core::List::[]}(dart.ffi::_abi())); set y(dart.core::double* #v) → void - return dart.ffi::_storeDouble(this.{dart.ffi::Struct::_addressOf}, (#C15).{dart.core::List::[]}(dart.ffi::_abi()), #v); + return dart.ffi::_storeDouble(this.{dart.ffi::Struct::_addressOf}, (#C16).{dart.core::List::[]}(dart.ffi::_abi()), #v); get next() → dart.ffi::Pointer* - return dart.ffi::_fromAddress(dart.ffi::_loadIntPtr(this.{dart.ffi::Struct::_addressOf}, (#C17).{dart.core::List::[]}(dart.ffi::_abi()))); + return dart.ffi::_fromAddress(dart.ffi::_loadIntPtr(this.{dart.ffi::Struct::_addressOf}, (#C18).{dart.core::List::[]}(dart.ffi::_abi()))); set next(dart.ffi::Pointer* #v) → void - return dart.ffi::_storeIntPtr(this.{dart.ffi::Struct::_addressOf}, (#C17).{dart.core::List::[]}(dart.ffi::_abi()), #v.{dart.ffi::Pointer::address}); + return dart.ffi::_storeIntPtr(this.{dart.ffi::Struct::_addressOf}, (#C18).{dart.core::List::[]}(dart.ffi::_abi()), #v.{dart.ffi::Pointer::address}); } } library from "org-dartlang-test:///main.dart" as main { @@ -63,14 +63,15 @@ constants { #C5 = TypeLiteralConstant(dart.ffi::Double) #C6 = TypeLiteralConstant(dart.ffi::Pointer) #C7 = [#C5, #C5, #C6] - #C8 = dart.core::pragma {name:#C4, options:#C7} - #C9 = 24 - #C10 = 20 - #C11 = [#C9, #C10, #C9] - #C12 = 0 - #C13 = [#C12, #C12, #C12] - #C14 = 8 - #C15 = [#C14, #C14, #C14] - #C16 = 16 - #C17 = [#C16, #C16, #C16] + #C8 = dart.ffi::_FfiStructLayout {fieldTypes:#C7} + #C9 = dart.core::pragma {name:#C4, options:#C8} + #C10 = 24 + #C11 = 20 + #C12 = [#C10, #C11, #C10] + #C13 = 0 + #C14 = [#C13, #C13, #C13] + #C15 = 8 + #C16 = [#C15, #C15, #C15] + #C17 = 16 + #C18 = [#C17, #C17, #C17] } diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/ffi_02.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/ffi_02.yaml.world.1.expect index 5d79437d8423..a42b6b2240b2 100644 --- a/pkg/front_end/testcases/incremental_initialize_from_dill/ffi_02.yaml.world.1.expect +++ b/pkg/front_end/testcases/incremental_initialize_from_dill/ffi_02.yaml.world.1.expect @@ -4,10 +4,10 @@ library from "org-dartlang-test:///lib.dart" as lib { import "dart:ffi"; @#C3 - @#C8 + @#C9 class Coordinate extends dart.ffi::Struct { @#C3 - static final field dart.core::int* #sizeOf = (#C11).{dart.core::List::[]}(dart.ffi::_abi()); + static final field dart.core::int* #sizeOf = (#C12).{dart.core::List::[]}(dart.ffi::_abi()); @#C3 constructor #fromTypedDataBase(dynamic #pointer) → dynamic : super dart.ffi::Struct::_fromPointer(#pointer) @@ -27,17 +27,17 @@ library from "org-dartlang-test:///lib.dart" as lib { abstract member-signature method noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod abstract member-signature get runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType get x() → dart.core::double* - return dart.ffi::_loadDouble(this.{dart.ffi::Struct::_addressOf}, (#C13).{dart.core::List::[]}(dart.ffi::_abi())); + return dart.ffi::_loadDouble(this.{dart.ffi::Struct::_addressOf}, (#C14).{dart.core::List::[]}(dart.ffi::_abi())); set x(dart.core::double* #v) → void - return dart.ffi::_storeDouble(this.{dart.ffi::Struct::_addressOf}, (#C13).{dart.core::List::[]}(dart.ffi::_abi()), #v); + return dart.ffi::_storeDouble(this.{dart.ffi::Struct::_addressOf}, (#C14).{dart.core::List::[]}(dart.ffi::_abi()), #v); get y() → dart.core::double* - return dart.ffi::_loadDouble(this.{dart.ffi::Struct::_addressOf}, (#C15).{dart.core::List::[]}(dart.ffi::_abi())); + return dart.ffi::_loadDouble(this.{dart.ffi::Struct::_addressOf}, (#C16).{dart.core::List::[]}(dart.ffi::_abi())); set y(dart.core::double* #v) → void - return dart.ffi::_storeDouble(this.{dart.ffi::Struct::_addressOf}, (#C15).{dart.core::List::[]}(dart.ffi::_abi()), #v); + return dart.ffi::_storeDouble(this.{dart.ffi::Struct::_addressOf}, (#C16).{dart.core::List::[]}(dart.ffi::_abi()), #v); get next() → dart.ffi::Pointer* - return dart.ffi::_fromAddress(dart.ffi::_loadIntPtr(this.{dart.ffi::Struct::_addressOf}, (#C17).{dart.core::List::[]}(dart.ffi::_abi()))); + return dart.ffi::_fromAddress(dart.ffi::_loadIntPtr(this.{dart.ffi::Struct::_addressOf}, (#C18).{dart.core::List::[]}(dart.ffi::_abi()))); set next(dart.ffi::Pointer* #v) → void - return dart.ffi::_storeIntPtr(this.{dart.ffi::Struct::_addressOf}, (#C17).{dart.core::List::[]}(dart.ffi::_abi()), #v.{dart.ffi::Pointer::address}); + return dart.ffi::_storeIntPtr(this.{dart.ffi::Struct::_addressOf}, (#C18).{dart.core::List::[]}(dart.ffi::_abi()), #v.{dart.ffi::Pointer::address}); } } library from "org-dartlang-test:///main.dart" as main { @@ -60,14 +60,15 @@ constants { #C5 = TypeLiteralConstant(dart.ffi::Double) #C6 = TypeLiteralConstant(dart.ffi::Pointer) #C7 = [#C5, #C5, #C6] - #C8 = dart.core::pragma {name:#C4, options:#C7} - #C9 = 24 - #C10 = 20 - #C11 = [#C9, #C10, #C9] - #C12 = 0 - #C13 = [#C12, #C12, #C12] - #C14 = 8 - #C15 = [#C14, #C14, #C14] - #C16 = 16 - #C17 = [#C16, #C16, #C16] + #C8 = dart.ffi::_FfiStructLayout {fieldTypes:#C7} + #C9 = dart.core::pragma {name:#C4, options:#C8} + #C10 = 24 + #C11 = 20 + #C12 = [#C10, #C11, #C10] + #C13 = 0 + #C14 = [#C13, #C13, #C13] + #C15 = 8 + #C16 = [#C15, #C15, #C15] + #C17 = 16 + #C18 = [#C17, #C17, #C17] } diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_35.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_35.yaml.world.1.expect index f93c1a3363e0..08f11e75bc3b 100644 --- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_35.yaml.world.1.expect +++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_35.yaml.world.1.expect @@ -4,10 +4,10 @@ library from "org-dartlang-test:///lib.dart" as lib { import "dart:ffi"; @#C3 - @#C8 + @#C9 class Coordinate extends dart.ffi::Struct { @#C3 - static final field dart.core::int* #sizeOf = (#C11).{dart.core::List::[]}(dart.ffi::_abi()); + static final field dart.core::int* #sizeOf = (#C12).{dart.core::List::[]}(dart.ffi::_abi()); @#C3 constructor #fromTypedDataBase(dynamic #pointer) → dynamic : super dart.ffi::Struct::_fromPointer(#pointer) @@ -27,17 +27,17 @@ library from "org-dartlang-test:///lib.dart" as lib { abstract member-signature method noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod abstract member-signature get runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType get x() → dart.core::double* - return dart.ffi::_loadDouble(this.{dart.ffi::Struct::_addressOf}, (#C13).{dart.core::List::[]}(dart.ffi::_abi())); + return dart.ffi::_loadDouble(this.{dart.ffi::Struct::_addressOf}, (#C14).{dart.core::List::[]}(dart.ffi::_abi())); set x(dart.core::double* #v) → void - return dart.ffi::_storeDouble(this.{dart.ffi::Struct::_addressOf}, (#C13).{dart.core::List::[]}(dart.ffi::_abi()), #v); + return dart.ffi::_storeDouble(this.{dart.ffi::Struct::_addressOf}, (#C14).{dart.core::List::[]}(dart.ffi::_abi()), #v); get y() → dart.core::double* - return dart.ffi::_loadDouble(this.{dart.ffi::Struct::_addressOf}, (#C15).{dart.core::List::[]}(dart.ffi::_abi())); + return dart.ffi::_loadDouble(this.{dart.ffi::Struct::_addressOf}, (#C16).{dart.core::List::[]}(dart.ffi::_abi())); set y(dart.core::double* #v) → void - return dart.ffi::_storeDouble(this.{dart.ffi::Struct::_addressOf}, (#C15).{dart.core::List::[]}(dart.ffi::_abi()), #v); + return dart.ffi::_storeDouble(this.{dart.ffi::Struct::_addressOf}, (#C16).{dart.core::List::[]}(dart.ffi::_abi()), #v); get next() → dart.ffi::Pointer* - return dart.ffi::_fromAddress(dart.ffi::_loadIntPtr(this.{dart.ffi::Struct::_addressOf}, (#C17).{dart.core::List::[]}(dart.ffi::_abi()))); + return dart.ffi::_fromAddress(dart.ffi::_loadIntPtr(this.{dart.ffi::Struct::_addressOf}, (#C18).{dart.core::List::[]}(dart.ffi::_abi()))); set next(dart.ffi::Pointer* #v) → void - return dart.ffi::_storeIntPtr(this.{dart.ffi::Struct::_addressOf}, (#C17).{dart.core::List::[]}(dart.ffi::_abi()), #v.{dart.ffi::Pointer::address}); + return dart.ffi::_storeIntPtr(this.{dart.ffi::Struct::_addressOf}, (#C18).{dart.core::List::[]}(dart.ffi::_abi()), #v.{dart.ffi::Pointer::address}); } } library from "org-dartlang-test:///main.dart" as main { @@ -59,14 +59,15 @@ constants { #C5 = TypeLiteralConstant(dart.ffi::Double) #C6 = TypeLiteralConstant(dart.ffi::Pointer) #C7 = [#C5, #C5, #C6] - #C8 = dart.core::pragma {name:#C4, options:#C7} - #C9 = 24 - #C10 = 20 - #C11 = [#C9, #C10, #C9] - #C12 = 0 - #C13 = [#C12, #C12, #C12] - #C14 = 8 - #C15 = [#C14, #C14, #C14] - #C16 = 16 - #C17 = [#C16, #C16, #C16] + #C8 = dart.ffi::_FfiStructLayout {fieldTypes:#C7} + #C9 = dart.core::pragma {name:#C4, options:#C8} + #C10 = 24 + #C11 = 20 + #C12 = [#C10, #C11, #C10] + #C13 = 0 + #C14 = [#C13, #C13, #C13] + #C15 = 8 + #C16 = [#C15, #C15, #C15] + #C17 = 16 + #C18 = [#C17, #C17, #C17] } diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_35.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_35.yaml.world.2.expect index 01f4106fe434..4d2947119f41 100644 --- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_35.yaml.world.2.expect +++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_35.yaml.world.2.expect @@ -4,10 +4,10 @@ library from "org-dartlang-test:///lib.dart" as lib { import "dart:ffi"; @#C3 - @#C8 + @#C9 class Coordinate extends dart.ffi::Struct { @#C3 - static final field dart.core::int* #sizeOf = (#C11).{dart.core::List::[]}(dart.ffi::_abi()); + static final field dart.core::int* #sizeOf = (#C12).{dart.core::List::[]}(dart.ffi::_abi()); @#C3 constructor #fromTypedDataBase(dynamic #pointer) → dynamic : super dart.ffi::Struct::_fromPointer(#pointer) @@ -27,17 +27,17 @@ library from "org-dartlang-test:///lib.dart" as lib { abstract member-signature method noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod abstract member-signature get runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType get x() → dart.core::double* - return dart.ffi::_loadDouble(this.{dart.ffi::Struct::_addressOf}, (#C13).{dart.core::List::[]}(dart.ffi::_abi())); + return dart.ffi::_loadDouble(this.{dart.ffi::Struct::_addressOf}, (#C14).{dart.core::List::[]}(dart.ffi::_abi())); set x(dart.core::double* #v) → void - return dart.ffi::_storeDouble(this.{dart.ffi::Struct::_addressOf}, (#C13).{dart.core::List::[]}(dart.ffi::_abi()), #v); + return dart.ffi::_storeDouble(this.{dart.ffi::Struct::_addressOf}, (#C14).{dart.core::List::[]}(dart.ffi::_abi()), #v); get y() → dart.core::double* - return dart.ffi::_loadDouble(this.{dart.ffi::Struct::_addressOf}, (#C15).{dart.core::List::[]}(dart.ffi::_abi())); + return dart.ffi::_loadDouble(this.{dart.ffi::Struct::_addressOf}, (#C16).{dart.core::List::[]}(dart.ffi::_abi())); set y(dart.core::double* #v) → void - return dart.ffi::_storeDouble(this.{dart.ffi::Struct::_addressOf}, (#C15).{dart.core::List::[]}(dart.ffi::_abi()), #v); + return dart.ffi::_storeDouble(this.{dart.ffi::Struct::_addressOf}, (#C16).{dart.core::List::[]}(dart.ffi::_abi()), #v); get next() → dart.ffi::Pointer* - return dart.ffi::_fromAddress(dart.ffi::_loadIntPtr(this.{dart.ffi::Struct::_addressOf}, (#C17).{dart.core::List::[]}(dart.ffi::_abi()))); + return dart.ffi::_fromAddress(dart.ffi::_loadIntPtr(this.{dart.ffi::Struct::_addressOf}, (#C18).{dart.core::List::[]}(dart.ffi::_abi()))); set next(dart.ffi::Pointer* #v) → void - return dart.ffi::_storeIntPtr(this.{dart.ffi::Struct::_addressOf}, (#C17).{dart.core::List::[]}(dart.ffi::_abi()), #v.{dart.ffi::Pointer::address}); + return dart.ffi::_storeIntPtr(this.{dart.ffi::Struct::_addressOf}, (#C18).{dart.core::List::[]}(dart.ffi::_abi()), #v.{dart.ffi::Pointer::address}); } } library from "org-dartlang-test:///main.dart" as main { @@ -60,14 +60,15 @@ constants { #C5 = TypeLiteralConstant(dart.ffi::Double) #C6 = TypeLiteralConstant(dart.ffi::Pointer) #C7 = [#C5, #C5, #C6] - #C8 = dart.core::pragma {name:#C4, options:#C7} - #C9 = 24 - #C10 = 20 - #C11 = [#C9, #C10, #C9] - #C12 = 0 - #C13 = [#C12, #C12, #C12] - #C14 = 8 - #C15 = [#C14, #C14, #C14] - #C16 = 16 - #C17 = [#C16, #C16, #C16] + #C8 = dart.ffi::_FfiStructLayout {fieldTypes:#C7} + #C9 = dart.core::pragma {name:#C4, options:#C8} + #C10 = 24 + #C11 = 20 + #C12 = [#C10, #C11, #C10] + #C13 = 0 + #C14 = [#C13, #C13, #C13] + #C15 = 8 + #C16 = [#C15, #C15, #C15] + #C17 = 16 + #C18 = [#C17, #C17, #C17] } diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_35.yaml.world.3.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_35.yaml.world.3.expect index 2c057afb065a..6f18d43c35a7 100644 --- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_35.yaml.world.3.expect +++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_35.yaml.world.3.expect @@ -4,10 +4,10 @@ library from "org-dartlang-test:///lib.dart" as lib { import "dart:ffi"; @#C3 - @#C8 + @#C9 class Coordinate extends dart.ffi::Struct { @#C3 - static final field dart.core::int* #sizeOf = (#C11).{dart.core::List::[]}(dart.ffi::_abi()); + static final field dart.core::int* #sizeOf = (#C12).{dart.core::List::[]}(dart.ffi::_abi()); @#C3 constructor #fromTypedDataBase(dynamic #pointer) → dynamic : super dart.ffi::Struct::_fromPointer(#pointer) @@ -28,17 +28,17 @@ library from "org-dartlang-test:///lib.dart" as lib { abstract member-signature method noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod abstract member-signature get runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType get x() → dart.core::double* - return dart.ffi::_loadDouble(this.{dart.ffi::Struct::_addressOf}, (#C13).{dart.core::List::[]}(dart.ffi::_abi())); + return dart.ffi::_loadDouble(this.{dart.ffi::Struct::_addressOf}, (#C14).{dart.core::List::[]}(dart.ffi::_abi())); set x(dart.core::double* #v) → void - return dart.ffi::_storeDouble(this.{dart.ffi::Struct::_addressOf}, (#C13).{dart.core::List::[]}(dart.ffi::_abi()), #v); + return dart.ffi::_storeDouble(this.{dart.ffi::Struct::_addressOf}, (#C14).{dart.core::List::[]}(dart.ffi::_abi()), #v); get y() → dart.core::double* - return dart.ffi::_loadDouble(this.{dart.ffi::Struct::_addressOf}, (#C15).{dart.core::List::[]}(dart.ffi::_abi())); + return dart.ffi::_loadDouble(this.{dart.ffi::Struct::_addressOf}, (#C16).{dart.core::List::[]}(dart.ffi::_abi())); set y(dart.core::double* #v) → void - return dart.ffi::_storeDouble(this.{dart.ffi::Struct::_addressOf}, (#C15).{dart.core::List::[]}(dart.ffi::_abi()), #v); + return dart.ffi::_storeDouble(this.{dart.ffi::Struct::_addressOf}, (#C16).{dart.core::List::[]}(dart.ffi::_abi()), #v); get next() → dart.ffi::Pointer* - return dart.ffi::_fromAddress(dart.ffi::_loadIntPtr(this.{dart.ffi::Struct::_addressOf}, (#C17).{dart.core::List::[]}(dart.ffi::_abi()))); + return dart.ffi::_fromAddress(dart.ffi::_loadIntPtr(this.{dart.ffi::Struct::_addressOf}, (#C18).{dart.core::List::[]}(dart.ffi::_abi()))); set next(dart.ffi::Pointer* #v) → void - return dart.ffi::_storeIntPtr(this.{dart.ffi::Struct::_addressOf}, (#C17).{dart.core::List::[]}(dart.ffi::_abi()), #v.{dart.ffi::Pointer::address}); + return dart.ffi::_storeIntPtr(this.{dart.ffi::Struct::_addressOf}, (#C18).{dart.core::List::[]}(dart.ffi::_abi()), #v.{dart.ffi::Pointer::address}); } } library from "org-dartlang-test:///main.dart" as main { @@ -61,14 +61,15 @@ constants { #C5 = TypeLiteralConstant(dart.ffi::Double) #C6 = TypeLiteralConstant(dart.ffi::Pointer) #C7 = [#C5, #C5, #C6] - #C8 = dart.core::pragma {name:#C4, options:#C7} - #C9 = 24 - #C10 = 20 - #C11 = [#C9, #C10, #C9] - #C12 = 0 - #C13 = [#C12, #C12, #C12] - #C14 = 8 - #C15 = [#C14, #C14, #C14] - #C16 = 16 - #C17 = [#C16, #C16, #C16] + #C8 = dart.ffi::_FfiStructLayout {fieldTypes:#C7} + #C9 = dart.core::pragma {name:#C4, options:#C8} + #C10 = 24 + #C11 = 20 + #C12 = [#C10, #C11, #C10] + #C13 = 0 + #C14 = [#C13, #C13, #C13] + #C15 = 8 + #C16 = [#C15, #C15, #C15] + #C17 = 16 + #C18 = [#C17, #C17, #C17] } diff --git a/pkg/front_end/testcases/nnbd/ffi_sample.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/ffi_sample.dart.strong.transformed.expect index 79439bc1b470..e8d05335fde9 100644 --- a/pkg/front_end/testcases/nnbd/ffi_sample.dart.strong.transformed.expect +++ b/pkg/front_end/testcases/nnbd/ffi_sample.dart.strong.transformed.expect @@ -12,30 +12,30 @@ import "dart:ffi"; import "package:ffi/ffi.dart"; @#C3 -@#C8 +@#C9 class Coordinate extends ffi::Struct { @#C3 - static final field core::int* #sizeOf = (#C11).{core::List::[]}(ffi::_abi())/*isLegacy*/; + static final field core::int* #sizeOf = (#C12).{core::List::[]}(ffi::_abi())/*isLegacy*/; @#C3 constructor #fromTypedDataBase(dynamic #pointer) → dynamic : super ffi::Struct::_fromPointer(#pointer) ; - @#C12 + @#C13 get x() → core::double - return ffi::_loadDouble(this.{ffi::Struct::_addressOf}, (#C14).{core::List::[]}(ffi::_abi())); - @#C12 + return ffi::_loadDouble(this.{ffi::Struct::_addressOf}, (#C15).{core::List::[]}(ffi::_abi())); + @#C13 set x(core::double #externalFieldValue) → void - return ffi::_storeDouble(this.{ffi::Struct::_addressOf}, (#C14).{core::List::[]}(ffi::_abi()), #externalFieldValue); - @#C12 + return ffi::_storeDouble(this.{ffi::Struct::_addressOf}, (#C15).{core::List::[]}(ffi::_abi()), #externalFieldValue); + @#C13 get y() → core::double - return ffi::_loadDouble(this.{ffi::Struct::_addressOf}, (#C16).{core::List::[]}(ffi::_abi())); - @#C12 + return ffi::_loadDouble(this.{ffi::Struct::_addressOf}, (#C17).{core::List::[]}(ffi::_abi())); + @#C13 set y(core::double #externalFieldValue) → void - return ffi::_storeDouble(this.{ffi::Struct::_addressOf}, (#C16).{core::List::[]}(ffi::_abi()), #externalFieldValue); + return ffi::_storeDouble(this.{ffi::Struct::_addressOf}, (#C17).{core::List::[]}(ffi::_abi()), #externalFieldValue); get next() → ffi::Pointer - return ffi::_fromAddress(ffi::_loadIntPtr(this.{ffi::Struct::_addressOf}, (#C18).{core::List::[]}(ffi::_abi()))); + return ffi::_fromAddress(ffi::_loadIntPtr(this.{ffi::Struct::_addressOf}, (#C19).{core::List::[]}(ffi::_abi()))); set next(ffi::Pointer #externalFieldValue) → void - return ffi::_storeIntPtr(this.{ffi::Struct::_addressOf}, (#C18).{core::List::[]}(ffi::_abi()), #externalFieldValue.{ffi::Pointer::address}); + return ffi::_storeIntPtr(this.{ffi::Struct::_addressOf}, (#C19).{core::List::[]}(ffi::_abi()), #externalFieldValue.{ffi::Pointer::address}); static factory allocate(ffi::Allocator allocator, core::double x, core::double y, ffi::Pointer next) → self::Coordinate { return let final self::Coordinate #t1 = new self::Coordinate::#fromTypedDataBase(allocator.{ffi::Allocator::allocate}(self::Coordinate::#sizeOf)!) in block { #t1.{self::Coordinate::x} = x; @@ -54,17 +54,18 @@ constants { #C5 = TypeLiteralConstant(ffi::Double) #C6 = TypeLiteralConstant(ffi::Pointer) #C7 = [#C5, #C5, #C6] - #C8 = core::pragma {name:#C4, options:#C7} - #C9 = 24 - #C10 = 20 - #C11 = [#C9, #C10, #C9] - #C12 = ffi::Double {} - #C13 = 0 - #C14 = [#C13, #C13, #C13] - #C15 = 8 - #C16 = [#C15, #C15, #C15] - #C17 = 16 - #C18 = [#C17, #C17, #C17] + #C8 = ffi::_FfiStructLayout {fieldTypes:#C7} + #C9 = core::pragma {name:#C4, options:#C8} + #C10 = 24 + #C11 = 20 + #C12 = [#C10, #C11, #C10] + #C13 = ffi::Double {} + #C14 = 0 + #C15 = [#C14, #C14, #C14] + #C16 = 8 + #C17 = [#C16, #C16, #C16] + #C18 = 16 + #C19 = [#C18, #C18, #C18] } diff --git a/pkg/front_end/testcases/nnbd/ffi_sample.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/ffi_sample.dart.weak.transformed.expect index 79439bc1b470..e8d05335fde9 100644 --- a/pkg/front_end/testcases/nnbd/ffi_sample.dart.weak.transformed.expect +++ b/pkg/front_end/testcases/nnbd/ffi_sample.dart.weak.transformed.expect @@ -12,30 +12,30 @@ import "dart:ffi"; import "package:ffi/ffi.dart"; @#C3 -@#C8 +@#C9 class Coordinate extends ffi::Struct { @#C3 - static final field core::int* #sizeOf = (#C11).{core::List::[]}(ffi::_abi())/*isLegacy*/; + static final field core::int* #sizeOf = (#C12).{core::List::[]}(ffi::_abi())/*isLegacy*/; @#C3 constructor #fromTypedDataBase(dynamic #pointer) → dynamic : super ffi::Struct::_fromPointer(#pointer) ; - @#C12 + @#C13 get x() → core::double - return ffi::_loadDouble(this.{ffi::Struct::_addressOf}, (#C14).{core::List::[]}(ffi::_abi())); - @#C12 + return ffi::_loadDouble(this.{ffi::Struct::_addressOf}, (#C15).{core::List::[]}(ffi::_abi())); + @#C13 set x(core::double #externalFieldValue) → void - return ffi::_storeDouble(this.{ffi::Struct::_addressOf}, (#C14).{core::List::[]}(ffi::_abi()), #externalFieldValue); - @#C12 + return ffi::_storeDouble(this.{ffi::Struct::_addressOf}, (#C15).{core::List::[]}(ffi::_abi()), #externalFieldValue); + @#C13 get y() → core::double - return ffi::_loadDouble(this.{ffi::Struct::_addressOf}, (#C16).{core::List::[]}(ffi::_abi())); - @#C12 + return ffi::_loadDouble(this.{ffi::Struct::_addressOf}, (#C17).{core::List::[]}(ffi::_abi())); + @#C13 set y(core::double #externalFieldValue) → void - return ffi::_storeDouble(this.{ffi::Struct::_addressOf}, (#C16).{core::List::[]}(ffi::_abi()), #externalFieldValue); + return ffi::_storeDouble(this.{ffi::Struct::_addressOf}, (#C17).{core::List::[]}(ffi::_abi()), #externalFieldValue); get next() → ffi::Pointer - return ffi::_fromAddress(ffi::_loadIntPtr(this.{ffi::Struct::_addressOf}, (#C18).{core::List::[]}(ffi::_abi()))); + return ffi::_fromAddress(ffi::_loadIntPtr(this.{ffi::Struct::_addressOf}, (#C19).{core::List::[]}(ffi::_abi()))); set next(ffi::Pointer #externalFieldValue) → void - return ffi::_storeIntPtr(this.{ffi::Struct::_addressOf}, (#C18).{core::List::[]}(ffi::_abi()), #externalFieldValue.{ffi::Pointer::address}); + return ffi::_storeIntPtr(this.{ffi::Struct::_addressOf}, (#C19).{core::List::[]}(ffi::_abi()), #externalFieldValue.{ffi::Pointer::address}); static factory allocate(ffi::Allocator allocator, core::double x, core::double y, ffi::Pointer next) → self::Coordinate { return let final self::Coordinate #t1 = new self::Coordinate::#fromTypedDataBase(allocator.{ffi::Allocator::allocate}(self::Coordinate::#sizeOf)!) in block { #t1.{self::Coordinate::x} = x; @@ -54,17 +54,18 @@ constants { #C5 = TypeLiteralConstant(ffi::Double) #C6 = TypeLiteralConstant(ffi::Pointer) #C7 = [#C5, #C5, #C6] - #C8 = core::pragma {name:#C4, options:#C7} - #C9 = 24 - #C10 = 20 - #C11 = [#C9, #C10, #C9] - #C12 = ffi::Double {} - #C13 = 0 - #C14 = [#C13, #C13, #C13] - #C15 = 8 - #C16 = [#C15, #C15, #C15] - #C17 = 16 - #C18 = [#C17, #C17, #C17] + #C8 = ffi::_FfiStructLayout {fieldTypes:#C7} + #C9 = core::pragma {name:#C4, options:#C8} + #C10 = 24 + #C11 = 20 + #C12 = [#C10, #C11, #C10] + #C13 = ffi::Double {} + #C14 = 0 + #C15 = [#C14, #C14, #C14] + #C16 = 8 + #C17 = [#C16, #C16, #C16] + #C18 = 16 + #C19 = [#C18, #C18, #C18] } diff --git a/pkg/vm/lib/transformations/ffi.dart b/pkg/vm/lib/transformations/ffi.dart index 5ead3927a3b3..ea4ae29d04f9 100644 --- a/pkg/vm/lib/transformations/ffi.dart +++ b/pkg/vm/lib/transformations/ffi.dart @@ -214,6 +214,8 @@ class FfiTransformer extends Transformer { final Class opaqueClass; final Class pointerClass; final Class structClass; + final Class ffiStructLayoutClass; + final Field ffiStructLayoutTypesField; final Procedure allocateMethod; final Procedure allocatorAllocateMethod; final Procedure castMethod; @@ -274,6 +276,9 @@ class FfiTransformer extends Transformer { opaqueClass = index.getClass('dart:ffi', 'Opaque'), pointerClass = index.getClass('dart:ffi', 'Pointer'), structClass = index.getClass('dart:ffi', 'Struct'), + ffiStructLayoutClass = index.getClass('dart:ffi', '_FfiStructLayout'), + ffiStructLayoutTypesField = + index.getMember('dart:ffi', '_FfiStructLayout', 'fieldTypes'), allocateMethod = index.getMember('dart:ffi', 'AllocatorAlloc', 'call'), allocatorAllocateMethod = index.getMember('dart:ffi', 'Allocator', 'allocate'), diff --git a/pkg/vm/lib/transformations/ffi_definitions.dart b/pkg/vm/lib/transformations/ffi_definitions.dart index b06c63fb26af..7d67c8a7b5bd 100644 --- a/pkg/vm/lib/transformations/ffi_definitions.dart +++ b/pkg/vm/lib/transformations/ffi_definitions.dart @@ -474,7 +474,7 @@ class _FfiDefinitionTransformer extends FfiTransformer { } void _annoteStructWithFields(Class node, List fieldTypes) { - final types = fieldTypes.map((Class c) { + final constants = fieldTypes.map((Class c) { List typeArg = const []; if (c == pointerClass) { typeArg = [ @@ -488,10 +488,11 @@ class _FfiDefinitionTransformer extends FfiTransformer { node.addAnnotation(ConstantExpression( InstanceConstant(pragmaClass.reference, [], { pragmaName.getterReference: StringConstant("vm:ffi:struct-fields"), - // TODO(dartbug.com/38158): Wrap list in class to be able to encode - // more information when needed. - pragmaOptions.getterReference: ListConstant( - InterfaceType(typeClass, Nullability.nonNullable), types) + pragmaOptions.getterReference: + InstanceConstant(ffiStructLayoutClass.reference, [], { + ffiStructLayoutTypesField.getterReference: ListConstant( + InterfaceType(typeClass, Nullability.nonNullable), constants) + }) }), InterfaceType(pragmaClass, Nullability.nonNullable, []))); } diff --git a/runtime/vm/compiler/backend/inliner.cc b/runtime/vm/compiler/backend/inliner.cc index ce2f680c4314..acb987e19b1b 100644 --- a/runtime/vm/compiler/backend/inliner.cc +++ b/runtime/vm/compiler/backend/inliner.cc @@ -2266,13 +2266,15 @@ static bool IsInlineableOperator(const Function& function) { bool FlowGraphInliner::FunctionHasPreferInlinePragma(const Function& function) { Object& options = Object::Handle(); return Library::FindPragma(dart::Thread::Current(), /*only_core=*/false, - function, Symbols::vm_prefer_inline(), &options); + function, Symbols::vm_prefer_inline(), + /*multiple=*/false, &options); } bool FlowGraphInliner::FunctionHasNeverInlinePragma(const Function& function) { Object& options = Object::Handle(); return Library::FindPragma(dart::Thread::Current(), /*only_core=*/false, - function, Symbols::vm_never_inline(), &options); + function, Symbols::vm_never_inline(), + /*multiple=*/false, &options); } bool FlowGraphInliner::AlwaysInline(const Function& function) { @@ -2891,7 +2893,6 @@ static bool InlineByteArrayBaseLoad(FlowGraph* flow_graph, (*entry)->InheritDeoptTarget(Z, call); Instruction* cursor = *entry; - // Generates a template for the load, either a dynamic conditional // that dispatches on external and internal storage, or a single // case that deals with either external or internal storage. diff --git a/runtime/vm/compiler/backend/redundancy_elimination.cc b/runtime/vm/compiler/backend/redundancy_elimination.cc index 03d3c39e7a71..d63933eacb85 100644 --- a/runtime/vm/compiler/backend/redundancy_elimination.cc +++ b/runtime/vm/compiler/backend/redundancy_elimination.cc @@ -4230,7 +4230,8 @@ static bool IsMarkedWithNoInterrupts(const Function& function) { Object& options = Object::Handle(); return Library::FindPragma(dart::Thread::Current(), /*only_core=*/false, function, - Symbols::vm_unsafe_no_interrupts(), &options); + Symbols::vm_unsafe_no_interrupts(), + /*multiple=*/false, &options); } void CheckStackOverflowElimination::EliminateStackOverflow(FlowGraph* graph) { diff --git a/runtime/vm/compiler/backend/type_propagator_test.cc b/runtime/vm/compiler/backend/type_propagator_test.cc index a278009326ea..1090bc9cd90e 100644 --- a/runtime/vm/compiler/backend/type_propagator_test.cc +++ b/runtime/vm/compiler/backend/type_propagator_test.cc @@ -467,7 +467,7 @@ class C( zone, field_types.Length()); for (intptr_t i = 0; i < field_types.Length(); i++) { - field_type ^= field_types.At(i); - const NativeType& field_native_type = - NativeType::FromAbstractType(zone, field_type); - field_native_types.Add(&field_native_type); + field_instance ^= field_types.At(i); + if (field_instance.IsAbstractType()) { + // Subtype of NativeType: Struct, native integer or native float. + field_type ^= field_types.At(i); + const auto& field_native_type = + NativeType::FromAbstractType(zone, field_type); + field_native_types.Add(&field_native_type); + } else { + // Inline array. + // TODO(http://dartbug.com/35763): Implement this. + UNIMPLEMENTED(); + } } return NativeCompoundType::FromNativeTypes(zone, field_native_types); diff --git a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc index c93100325ce8..f8fd87c99cf6 100644 --- a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc +++ b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc @@ -1121,7 +1121,8 @@ Fragment BaseFlowGraphBuilder::BuildEntryPointsIntrospection() { Object& options = Object::Handle(Z); if (!Library::FindPragma(thread_, /*only_core=*/false, function, - Symbols::vm_trace_entrypoints(), &options) || + Symbols::vm_trace_entrypoints(), /*multiple=*/false, + &options) || options.IsNull() || !options.IsClosure()) { return Drop(); } diff --git a/runtime/vm/compiler/method_recognizer.cc b/runtime/vm/compiler/method_recognizer.cc index 3abd57b58743..6a6bd4135bc2 100644 --- a/runtime/vm/compiler/method_recognizer.cc +++ b/runtime/vm/compiler/method_recognizer.cc @@ -29,7 +29,8 @@ intptr_t MethodRecognizer::ResultCidFromPragma( auto Z = T->zone(); auto& option = Object::Handle(Z); if (Library::FindPragma(T, /*only_core=*/true, function_or_field, - Symbols::vm_exact_result_type(), &option)) { + Symbols::vm_exact_result_type(), + /*multiple=*/false, &option)) { if (option.IsType()) { return Type::Cast(option).type_class_id(); } else if (option.IsString()) { @@ -82,7 +83,8 @@ bool MethodRecognizer::HasNonNullableResultTypeFromPragma( auto Z = T->zone(); auto& option = Object::Handle(Z); if (Library::FindPragma(T, /*only_core=*/true, function_or_field, - Symbols::vm_non_nullable_result_type(), &option)) { + Symbols::vm_non_nullable_result_type(), + /*multiple=*/false, &option)) { return true; } @@ -203,9 +205,9 @@ bool MethodRecognizer::IsMarkedAsRecognized(const Function& function, ? &Function::Handle(function.ForwardingTarget()) : &function; Object& options = Object::Handle(); - bool is_recognized = - Library::FindPragma(Thread::Current(), /*only_core=*/true, *functionp, - Symbols::vm_recognized(), &options); + bool is_recognized = Library::FindPragma( + Thread::Current(), /*only_core=*/true, *functionp, + Symbols::vm_recognized(), /*multiple=*/false, &options); if (!is_recognized) return false; if (kind == nullptr) return true; diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc index 13082d62b312..4b38596329ca 100644 --- a/runtime/vm/object.cc +++ b/runtime/vm/object.cc @@ -3621,6 +3621,7 @@ bool Library::FindPragma(Thread* T, bool only_core, const Object& obj, const String& pragma_name, + bool multiple, Object* options) { auto IG = T->isolate_group(); auto Z = T->zone(); @@ -3666,6 +3667,13 @@ bool Library::FindPragma(Thread* T, Field::Handle(Z, pragma_class.LookupField(Symbols::options())); auto& pragma = Object::Handle(Z); + bool found = false; + auto& options_value = Object::Handle(Z); + auto& results = GrowableObjectArray::Handle(Z); + if (multiple) { + ASSERT(options != nullptr); + results ^= GrowableObjectArray::New(1); + } for (intptr_t i = 0; i < metadata.Length(); ++i) { pragma = metadata.At(i); if (pragma.clazz() != pragma_class.ptr() || @@ -3673,13 +3681,22 @@ bool Library::FindPragma(Thread* T, pragma_name.ptr()) { continue; } + options_value = Instance::Cast(pragma).GetField(pragma_options_field); + found = true; + if (multiple) { + results.Add(options_value); + continue; + } if (options != nullptr) { - *options = Instance::Cast(pragma).GetField(pragma_options_field); + *options = options_value.ptr(); } return true; } - return false; + if (found && options != nullptr) { + *options = results.ptr(); + } + return found; } bool Function::IsDynamicInvocationForwarderName(const String& name) { diff --git a/runtime/vm/object.h b/runtime/vm/object.h index d40a212cba12..5cf9f6cfb1b8 100644 --- a/runtime/vm/object.h +++ b/runtime/vm/object.h @@ -4658,12 +4658,16 @@ class Library : public Object { // If [only_core] is true, then the annotations on the object will only // be inspected if it is part of a core library. // + // If [multiple] is true, then sets [options] to an GrowableObjectArray + // containing all results and [options] may not be nullptr. + // // WARNING: If the isolate received an [UnwindError] this function will not // return and rather unwinds until the enclosing setjmp() handler. static bool FindPragma(Thread* T, bool only_core, const Object& object, const String& pragma_name, + bool multiple = false, Object* options = nullptr); ClassPtr toplevel_class() const { return untag()->toplevel_class(); } @@ -6144,11 +6148,9 @@ class Code : public Object { explicit Comments(const Array& comments); // Layout of entries describing comments. - enum { - kPCOffsetEntry = 0, // PC offset to a comment as a Smi. - kCommentEntry, // Comment text as a String. - kNumberOfEntries - }; + enum {kPCOffsetEntry = 0, // PC offset to a comment as a Smi. + kCommentEntry, // Comment text as a String. + kNumberOfEntries}; const Array& comments_; String& string_; diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h index 39dfa25f22ab..631c7a8c3fe1 100644 --- a/runtime/vm/symbols.h +++ b/runtime/vm/symbols.h @@ -124,6 +124,7 @@ class ObjectPointerVisitor; V(FfiCallback, "_FfiCallback") \ V(FfiDouble, "Double") \ V(FfiDynamicLibrary, "DynamicLibrary") \ + V(FfiFieldTypes, "fieldTypes") \ V(FfiFloat, "Float") \ V(FfiInt16, "Int16") \ V(FfiInt32, "Int32") \ @@ -133,6 +134,7 @@ class ObjectPointerVisitor; V(FfiNativeFunction, "NativeFunction") \ V(FfiNativeType, "NativeType") \ V(FfiPointer, "Pointer") \ + V(FfiStructLayout, "_FfiStructLayout") \ V(FfiTrampolineData, "FfiTrampolineData") \ V(FfiUint16, "Uint16") \ V(FfiUint32, "Uint32") \ diff --git a/sdk/lib/_internal/vm/lib/ffi_struct_patch.dart b/sdk/lib/_internal/vm/lib/ffi_struct_patch.dart index 8fad96754e12..489dd6e15d4a 100644 --- a/sdk/lib/_internal/vm/lib/ffi_struct_patch.dart +++ b/sdk/lib/_internal/vm/lib/ffi_struct_patch.dart @@ -10,3 +10,11 @@ import 'dart:isolate'; @pragma("vm:entry-point") abstract class Struct extends NativeType {} + +@pragma("vm:entry-point") +class _FfiStructLayout { + @pragma("vm:entry-point") + final List fieldTypes; + + const _FfiStructLayout(this.fieldTypes); +}