Skip to content

Commit fb624c4

Browse files
dcharkescommit-bot@chromium.org
authored andcommitted
Reland "[vm/ffi] Change Pointer<T extends Struct>.ref to use static type"
This CL changes the semantics of `Pointer<T extends Struct>.ref` to use the compile-time `T` rather than the runtime `T`. This enables tree shaking of subtypes of Struct and optimizing `.ref`. Bug: #38721 TEST=tests/ffi/vmspecific_static_checks_test.dart TEST=tests/ffi/*struct*test_.dart Change-Id: Ie19bc3259d1cb721d0ce56d68e82d09dc3a4ad0e Cq-Include-Trybots: luci.dart.try:analyzer-linux-release-try,analyzer-nnbd-linux-release-try,app-kernel-linux-debug-x64-try,dart-sdk-linux-try,front-end-nnbd-linux-release-x64-try,pkg-linux-debug-try,vm-kernel-linux-debug-x64-try,vm-kernel-nnbd-linux-debug-x64-try,vm-kernel-precomp-nnbd-linux-debug-x64-try,vm-kernel-reload-rollback-linux-debug-x64-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/180190 Commit-Queue: Daco Harkes <[email protected]> Reviewed-by: Aske Simon Christensen <[email protected]>
1 parent 7194e88 commit fb624c4

File tree

8 files changed

+31
-34
lines changed

8 files changed

+31
-34
lines changed

pkg/analyzer/lib/src/generated/ffi_verifier.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -785,7 +785,7 @@ class FfiVerifier extends RecursiveAstVisitor<void> {
785785
if (!_isValidFfiNativeType(targetType, false, true)) {
786786
final AstNode errorNode = node;
787787
_errorReporter.reportErrorForNode(
788-
FfiCode.NON_CONSTANT_TYPE_ARGUMENT_WARNING, errorNode, ['[]']);
788+
FfiCode.NON_CONSTANT_TYPE_ARGUMENT, errorNode, ['[]']);
789789
}
790790
}
791791

@@ -796,7 +796,7 @@ class FfiVerifier extends RecursiveAstVisitor<void> {
796796
if (!_isValidFfiNativeType(targetType, false, true)) {
797797
final AstNode errorNode = node;
798798
_errorReporter.reportErrorForNode(
799-
FfiCode.NON_CONSTANT_TYPE_ARGUMENT_WARNING, errorNode, ['ref']);
799+
FfiCode.NON_CONSTANT_TYPE_ARGUMENT, errorNode, ['ref']);
800800
}
801801
}
802802

@@ -805,7 +805,7 @@ class FfiVerifier extends RecursiveAstVisitor<void> {
805805
if (!_isValidFfiNativeType(targetType, false, true)) {
806806
final AstNode errorNode = node;
807807
_errorReporter.reportErrorForNode(
808-
FfiCode.NON_CONSTANT_TYPE_ARGUMENT_WARNING, errorNode, ['ref']);
808+
FfiCode.NON_CONSTANT_TYPE_ARGUMENT, errorNode, ['ref']);
809809
}
810810
}
811811

pkg/analyzer/test/src/diagnostics/non_constant_type_argument_test.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,6 @@ import 'dart:ffi';
7272
7373
T genericRef<T extends Struct>(Pointer<T> p) =>
7474
p.ref;
75-
''', [error(FfiCode.NON_CONSTANT_TYPE_ARGUMENT_WARNING, 72, 5)]);
75+
''', [error(FfiCode.NON_CONSTANT_TYPE_ARGUMENT, 72, 5)]);
7676
}
7777
}

pkg/vm/lib/transformations/ffi_use_sites.dart

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -184,13 +184,7 @@ class _FfiUseSiteTransformer extends FfiTransformer {
184184
if (target == structPointerRef || target == structPointerElemAt) {
185185
final DartType nativeType = node.arguments.types[0];
186186

187-
_warningNativeTypeValid(nativeType, node, allowStructItself: false);
188-
189-
// TODO(http://dartbug.com/38721): Change this to an error.
190-
if (nativeType is TypeParameterType) {
191-
// Do not rewire generic invocations.
192-
return node;
193-
}
187+
_ensureNativeTypeValid(nativeType, node, allowStructItself: false);
194188

195189
return _replaceRef(node);
196190
} else if (target == sizeOfMethod) {

runtime/lib/ffi.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ static ObjectPtr LoadValueStruct(Zone* zone,
116116
DEFINE_NATIVE_ENTRY(Ffi_loadStruct, 0, 2) {
117117
GET_NON_NULL_NATIVE_ARGUMENT(Pointer, pointer, arguments->NativeArgAt(0));
118118
const AbstractType& pointer_type_arg =
119-
AbstractType::Handle(pointer.type_argument());
119+
AbstractType::Handle(arguments->NativeTypeArgAt(0));
120120
GET_NON_NULL_NATIVE_ARGUMENT(Integer, index, arguments->NativeArgAt(1));
121121

122122
// TODO(36370): Make representation consistent with kUnboxedFfiIntPtr.

sdk/lib/_internal/vm/lib/ffi_patch.dart

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,13 @@ double _loadDouble(Pointer pointer, int offsetInBytes) native "Ffi_loadDouble";
204204
Pointer<S> _loadPointer<S extends NativeType>(
205205
Pointer pointer, int offsetInBytes) native "Ffi_loadPointer";
206206

207+
S _loadStructNoStruct<S extends Struct>(Pointer<S> pointer, int index) {
208+
if (S == Struct) {
209+
throw ArgumentError("S should be a subtype of Struct.");
210+
}
211+
return _loadStruct(pointer, index);
212+
}
213+
207214
S _loadStruct<S extends Struct>(Pointer<S> pointer, int index)
208215
native "Ffi_loadStruct";
209216

@@ -511,10 +518,10 @@ extension PointerPointer<T extends NativeType> on Pointer<Pointer<T>> {
511518

512519
extension StructPointer<T extends Struct> on Pointer<T> {
513520
@patch
514-
T get ref => _loadStruct(this, 0);
521+
T get ref => _loadStructNoStruct(this, 0);
515522

516523
@patch
517-
T operator [](int index) => _loadStruct(this, index);
524+
T operator [](int index) => _loadStructNoStruct(this, index);
518525
}
519526

520527
extension NativePort on SendPort {

sdk/lib/ffi/ffi.dart

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -545,9 +545,7 @@ extension StructPointer<T extends Struct> on Pointer<T> {
545545
/// The [address] must be aligned according to the struct alignment rules of
546546
/// the platform.
547547
///
548-
/// Support for invoking this extension method with non-constant [T] will be
549-
/// removed in the next stable version of Dart and it will become mandatory
550-
/// to invoke it with a compile-time constant [T].
548+
/// This extension method must be invoked with a compile-time constant [T].
551549
external T get ref;
552550

553551
/// Creates a reference to access the fields of this struct backed by native
@@ -556,9 +554,7 @@ extension StructPointer<T extends Struct> on Pointer<T> {
556554
/// The [address] must be aligned according to the struct alignment rules of
557555
/// the platform.
558556
///
559-
/// Support for invoking this extension method with non-constant [T] will be
560-
/// removed in the next stable version of Dart and it will become mandatory
561-
/// to invoke it with a compile-time constant [T].
557+
/// This extension method must be invoked with a compile-time constant [T].
562558
external T operator [](int index);
563559
}
564560

tests/ffi/vmspecific_static_checks_test.dart

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -610,18 +610,18 @@ void testAllocateNativeType() {
610610
void testRefStruct() {
611611
final myStructPointer = calloc<TestStruct13>();
612612
Pointer<Struct> structPointer = myStructPointer;
613-
structPointer.ref; //# 1330: ok
613+
structPointer.ref; //# 1330: compile-time error
614614
calloc.free(myStructPointer);
615615
}
616616

617-
T genericRef<T extends Struct>(Pointer<T> p) => //# 1200: ok
618-
p.ref; //# 1200: ok
617+
T genericRef<T extends Struct>(Pointer<T> p) => //# 1200: compile-time error
618+
p.ref; //# 1200: compile-time error
619619

620-
T genericRef2<T extends Struct>(Pointer<T> p) => //# 1201: ok
621-
p.cast<T>().ref; //# 1201: ok
620+
T genericRef2<T extends Struct>(Pointer<T> p) => //# 1201: compile-time error
621+
p.cast<T>().ref; //# 1201: compile-time error
622622

623-
T genericRef3<T extends Struct>(Pointer<T> p) => //# 1202: ok
624-
p[0]; //# 1202: ok
623+
T genericRef3<T extends Struct>(Pointer<T> p) => //# 1202: compile-time error
624+
p[0]; //# 1202: compile-time error
625625

626626
void testSizeOfGeneric() {
627627
int generic<T extends Pointer>() {

tests/ffi_2/vmspecific_static_checks_test.dart

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -608,18 +608,18 @@ void testAllocateNativeType() {
608608
void testRefStruct() {
609609
final myStructPointer = calloc<TestStruct13>();
610610
Pointer<Struct> structPointer = myStructPointer;
611-
structPointer.ref; //# 1330: ok
611+
structPointer.ref; //# 1330: compile-time error
612612
calloc.free(myStructPointer);
613613
}
614614

615-
T genericRef<T extends Struct>(Pointer<T> p) => //# 1200: ok
616-
p.ref; //# 1200: ok
615+
T genericRef<T extends Struct>(Pointer<T> p) => //# 1200: compile-time error
616+
p.ref; //# 1200: compile-time error
617617

618-
T genericRef2<T extends Struct>(Pointer<T> p) => //# 1201: ok
619-
p.cast<T>().ref; //# 1201: ok
618+
T genericRef2<T extends Struct>(Pointer<T> p) => //# 1201: compile-time error
619+
p.cast<T>().ref; //# 1201: compile-time error
620620

621-
T genericRef3<T extends Struct>(Pointer<T> p) => //# 1202: ok
622-
p[0]; //# 1202: ok
621+
T genericRef3<T extends Struct>(Pointer<T> p) => //# 1202: compile-time error
622+
p[0]; //# 1202: compile-time error
623623

624624
void testSizeOfGeneric() {
625625
int generic<T extends Pointer>() {

0 commit comments

Comments
 (0)