Skip to content

Commit 2435f0b

Browse files
dcharkesCommit Queue
authored and
Commit Queue
committed
[vm/ffi] Make elementAt an extension method
The CFE rewrite for structs, unions, and abi-specific integers is now done on the extension methods. The other native types are implemented in the extension methods directly. TEST=test/ffi Closes: #50714 Change-Id: I578325733e3cd66200e80949d47ff12a13115b99 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/276102 Reviewed-by: Slava Egorov <[email protected]> Commit-Queue: Daco Harkes <[email protected]>
1 parent 3d3fdc7 commit 2435f0b

File tree

6 files changed

+162
-122
lines changed

6 files changed

+162
-122
lines changed

pkg/vm/lib/transformations/ffi/common.dart

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ const Map<NativeType, int> nativeTypeSizes = <NativeType, int>{
113113
NativeType.kBool: 1,
114114
};
115115

116-
/// Load, store, and elementAt are rewired to their static type for these types.
116+
/// Load and store are rewired to their static type for these types.
117117
const List<NativeType> optimizedTypes = [
118118
NativeType.kBool,
119119
NativeType.kInt8,
@@ -201,16 +201,19 @@ class FfiTransformer extends Transformer {
201201
final Procedure allocatorAllocateMethod;
202202
final Procedure castMethod;
203203
final Procedure offsetByMethod;
204-
final Procedure elementAtMethod;
205204
final Procedure addressGetter;
206205
final Procedure structPointerGetRef;
207206
final Procedure structPointerSetRef;
208207
final Procedure structPointerGetElemAt;
209208
final Procedure structPointerSetElemAt;
209+
final Procedure structPointerElementAt;
210+
final Procedure structPointerElementAtTearoff;
210211
final Procedure unionPointerGetRef;
211212
final Procedure unionPointerSetRef;
212213
final Procedure unionPointerGetElemAt;
213214
final Procedure unionPointerSetElemAt;
215+
final Procedure unionPointerElementAt;
216+
final Procedure unionPointerElementAtTearoff;
214217
final Procedure structArrayElemAt;
215218
final Procedure unionArrayElemAt;
216219
final Procedure arrayArrayElemAt;
@@ -219,6 +222,8 @@ class FfiTransformer extends Transformer {
219222
final Procedure abiSpecificIntegerPointerSetValue;
220223
final Procedure abiSpecificIntegerPointerElemAt;
221224
final Procedure abiSpecificIntegerPointerSetElemAt;
225+
final Procedure abiSpecificIntegerPointerElementAt;
226+
final Procedure abiSpecificIntegerPointerElementAtTearoff;
222227
final Procedure abiSpecificIntegerArrayElemAt;
223228
final Procedure abiSpecificIntegerArraySetElemAt;
224229
final Procedure asFunctionMethod;
@@ -246,7 +251,6 @@ class FfiTransformer extends Transformer {
246251
final Map<NativeType, Procedure> loadUnalignedMethods;
247252
final Map<NativeType, Procedure> storeMethods;
248253
final Map<NativeType, Procedure> storeUnalignedMethods;
249-
final Map<NativeType, Procedure> elementAtMethods;
250254
final Procedure loadAbiSpecificIntMethod;
251255
final Procedure loadAbiSpecificIntAtIndexMethod;
252256
final Procedure storeAbiSpecificIntMethod;
@@ -363,8 +367,6 @@ class FfiTransformer extends Transformer {
363367
index.getProcedure('dart:ffi', 'Allocator', 'allocate'),
364368
castMethod = index.getProcedure('dart:ffi', 'Pointer', 'cast'),
365369
offsetByMethod = index.getProcedure('dart:ffi', 'Pointer', '_offsetBy'),
366-
elementAtMethod =
367-
index.getProcedure('dart:ffi', 'Pointer', 'elementAt'),
368370
addressGetter =
369371
index.getProcedure('dart:ffi', 'Pointer', 'get:address'),
370372
compoundTypedDataBaseField =
@@ -397,6 +399,10 @@ class FfiTransformer extends Transformer {
397399
index.getProcedure('dart:ffi', 'StructPointer', '[]'),
398400
structPointerSetElemAt =
399401
index.getProcedure('dart:ffi', 'StructPointer', '[]='),
402+
structPointerElementAt =
403+
index.getProcedure('dart:ffi', 'StructPointer', 'elementAt'),
404+
structPointerElementAtTearoff = index.getProcedure('dart:ffi',
405+
'StructPointer', LibraryIndex.tearoffPrefix + 'elementAt'),
400406
unionPointerGetRef =
401407
index.getProcedure('dart:ffi', 'UnionPointer', 'get:ref'),
402408
unionPointerSetRef =
@@ -405,6 +411,10 @@ class FfiTransformer extends Transformer {
405411
index.getProcedure('dart:ffi', 'UnionPointer', '[]'),
406412
unionPointerSetElemAt =
407413
index.getProcedure('dart:ffi', 'UnionPointer', '[]='),
414+
unionPointerElementAt =
415+
index.getProcedure('dart:ffi', 'UnionPointer', 'elementAt'),
416+
unionPointerElementAtTearoff = index.getProcedure('dart:ffi',
417+
'UnionPointer', LibraryIndex.tearoffPrefix + 'elementAt'),
408418
structArrayElemAt = index.getProcedure('dart:ffi', 'StructArray', '[]'),
409419
unionArrayElemAt = index.getProcedure('dart:ffi', 'UnionArray', '[]'),
410420
arrayArrayElemAt = index.getProcedure('dart:ffi', 'ArrayArray', '[]'),
@@ -418,6 +428,12 @@ class FfiTransformer extends Transformer {
418428
index.getProcedure('dart:ffi', 'AbiSpecificIntegerPointer', '[]'),
419429
abiSpecificIntegerPointerSetElemAt =
420430
index.getProcedure('dart:ffi', 'AbiSpecificIntegerPointer', '[]='),
431+
abiSpecificIntegerPointerElementAt = index.getProcedure(
432+
'dart:ffi', 'AbiSpecificIntegerPointer', 'elementAt'),
433+
abiSpecificIntegerPointerElementAtTearoff = index.getProcedure(
434+
'dart:ffi',
435+
'AbiSpecificIntegerPointer',
436+
LibraryIndex.tearoffPrefix + 'elementAt'),
421437
abiSpecificIntegerArrayElemAt =
422438
index.getProcedure('dart:ffi', 'AbiSpecificIntegerArray', '[]'),
423439
abiSpecificIntegerArraySetElemAt =
@@ -462,10 +478,6 @@ class FfiTransformer extends Transformer {
462478
return index.getTopLevelProcedure(
463479
'dart:ffi', "_store${name}Unaligned");
464480
}),
465-
elementAtMethods = Map.fromIterable(optimizedTypes, value: (t) {
466-
final name = nativeTypeClassNames[t];
467-
return index.getTopLevelProcedure('dart:ffi', "_elementAt$name");
468-
}),
469481
loadAbiSpecificIntMethod =
470482
index.getTopLevelProcedure('dart:ffi', "_loadAbiSpecificInt"),
471483
loadAbiSpecificIntAtIndexMethod = index.getTopLevelProcedure(

pkg/vm/lib/transformations/ffi/use_sites.dart

Lines changed: 26 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,10 @@ mixin _FfiUseSiteTransformer on FfiTransformer {
123123
node.isExtensionMember &&
124124
(node == allocationTearoff ||
125125
node == asFunctionTearoff ||
126-
node == lookupFunctionTearoff));
126+
node == lookupFunctionTearoff ||
127+
node == abiSpecificIntegerPointerElementAtTearoff ||
128+
node == structPointerElementAtTearoff ||
129+
node == unionPointerElementAtTearoff));
127130
final result = super.visitProcedure(node);
128131
_inFfiTearoff = false;
129132
return result;
@@ -201,6 +204,28 @@ mixin _FfiUseSiteTransformer on FfiTransformer {
201204
ensureNativeTypeValid(nativeType, node, allowCompounds: true);
202205

203206
return _replaceSetRef(node);
207+
} else if (target == abiSpecificIntegerPointerElementAt ||
208+
target == structPointerElementAt ||
209+
target == unionPointerElementAt) {
210+
final pointer = node.arguments.positional[0];
211+
final index = node.arguments.positional[1];
212+
final pointerType =
213+
pointer.getStaticType(staticTypeContext!) as InterfaceType;
214+
ensureNativeTypeValid(pointerType, pointer,
215+
allowCompounds: true, allowInlineArray: true);
216+
final DartType nativeType = node.arguments.types[0];
217+
218+
ensureNativeTypeValid(nativeType, node, allowCompounds: true);
219+
220+
Expression? inlineSizeOf = _inlineSizeOf(nativeType as InterfaceType);
221+
if (inlineSizeOf != null) {
222+
// Generates `receiver.offsetBy(inlineSizeOfExpression)`.
223+
return InstanceInvocation(InstanceAccessKind.Instance, pointer,
224+
offsetByMethod.name, Arguments([multiply(index, inlineSizeOf)]),
225+
interfaceTarget: offsetByMethod,
226+
functionType: Substitution.fromInterfaceType(pointerType)
227+
.substituteType(offsetByMethod.getterType) as FunctionType);
228+
}
204229
} else if (target == structArrayElemAt || target == unionArrayElemAt) {
205230
final DartType nativeType = node.arguments.types[0];
206231

@@ -704,60 +729,6 @@ mixin _FfiUseSiteTransformer on FfiTransformer {
704729
..fileOffset = node.fileOffset);
705730
}
706731

707-
@override
708-
visitInstanceInvocation(InstanceInvocation node) {
709-
final modifiedExpression = _visitInstanceInvocation(node);
710-
if (node == modifiedExpression) {
711-
return super.visitInstanceInvocation(node);
712-
}
713-
// We've just created this node. We're likely not going to need to transform
714-
// this node itself. Visit its sub expressions.
715-
return super.defaultExpression(modifiedExpression);
716-
}
717-
718-
/// Replaces nodes if they match. Does not invoke any super visit.
719-
Expression _visitInstanceInvocation(InstanceInvocation node) {
720-
if (_inFfiTearoff) {
721-
return node;
722-
}
723-
final Member target = node.interfaceTarget;
724-
try {
725-
if (target == elementAtMethod) {
726-
final DartType pointerType =
727-
node.receiver.getStaticType(staticTypeContext!);
728-
final DartType nativeType = _pointerTypeGetTypeArg(pointerType)!;
729-
730-
ensureNativeTypeValid(nativeType, node, allowCompounds: true);
731-
732-
Expression? inlineSizeOf = _inlineSizeOf(nativeType as InterfaceType);
733-
if (inlineSizeOf != null) {
734-
// Generates `receiver.offsetBy(inlineSizeOfExpression)`.
735-
return InstanceInvocation(
736-
InstanceAccessKind.Instance,
737-
node.receiver,
738-
offsetByMethod.name,
739-
Arguments(
740-
[multiply(node.arguments.positional.single, inlineSizeOf)]),
741-
interfaceTarget: offsetByMethod,
742-
functionType:
743-
Substitution.fromInterfaceType(pointerType as InterfaceType)
744-
.substituteType(offsetByMethod.getterType)
745-
as FunctionType);
746-
}
747-
}
748-
} on FfiStaticTypeError {
749-
// It's OK to swallow the exception because the diagnostics issued will
750-
// cause compilation to fail. By continuing, we can report more
751-
// diagnostics before compilation ends.
752-
}
753-
754-
return node;
755-
}
756-
757-
DartType? _pointerTypeGetTypeArg(DartType pointerType) {
758-
return pointerType is InterfaceType ? pointerType.typeArguments[0] : null;
759-
}
760-
761732
void _ensureIsStaticFunction(Expression node) {
762733
if ((node is StaticGet && node.target is Procedure) ||
763734
(node is ConstantExpression &&

runtime/tools/ffi/sdk_lib_ffi_generator.dart

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,9 @@ $platform$truncate$alignment external $dartType operator [](int index);
192192
/// The $property at `address + ${sizeTimes}index`.
193193
$platform$truncate$alignment external void operator []=(int index, $dartType value);
194194
195+
/// Pointer arithmetic (takes element size into account).
196+
external Pointer<$nativeType> elementAt(int index);
197+
195198
$asTypedList
196199
}
197200
@@ -237,7 +240,7 @@ void generatePatchExtension(
237240
if (container == "Pointer") {
238241
buffer.write("""
239242
extension ${nativeType}Pointer on Pointer<$nativeType> {
240-
@patch
243+
@patch
241244
$dartType get value => _load$nativeType(this, 0);
242245
243246
@patch
@@ -249,6 +252,9 @@ extension ${nativeType}Pointer on Pointer<$nativeType> {
249252
@patch
250253
operator []=(int index, $dartType value) => _store$nativeType(this, ${sizeTimes}index, value);
251254
255+
@patch
256+
Pointer<$nativeType> elementAt(int index) => Pointer.fromAddress(address + ${sizeTimes}index);
257+
252258
$asTypedList
253259
}
254260
@@ -329,9 +335,12 @@ class Config {
329335
final int elementSize;
330336
final Version? since;
331337
const Config(
332-
this.nativeType, this.dartType, this.typedListType, this.elementSize,
333-
{Version? since})
334-
: since = since;
338+
this.nativeType,
339+
this.dartType,
340+
this.typedListType,
341+
this.elementSize, {
342+
Version? since,
343+
}) : since = since;
335344
}
336345

337346
const String kDoNotEmit = "donotemit";

0 commit comments

Comments
 (0)