Skip to content

Commit 64bf734

Browse files
dcharkescommit-bot@chromium.org
authored andcommitted
[vm/ffi] Rewrite sizeOf calls in CFE
This rewrites `sizeOf` calls in the CFE to skip the runtime entry when the type argument is constant. The runtime entry is still used when the type argument is generic. Forcing the type argument to be constant and removing the runtime entry will be done in follow up CLs. Bug: #44621 Bug: #38721 TEST=tests/ffi/sizeof_test.dart Change-Id: I17d14432e6ab22810729be6b5c2939a033d382c5 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/182262 Reviewed-by: Clement Skau <[email protected]>
1 parent a42244f commit 64bf734

File tree

5 files changed

+94
-30
lines changed

5 files changed

+94
-30
lines changed

pkg/vm/lib/transformations/ffi.dart

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,13 +410,32 @@ class FfiTransformer extends Transformer {
410410
return FunctionType(argumentTypes, returnType, Nullability.legacy);
411411
}
412412

413+
/// The [NativeType] corresponding to [c]. Returns `null` for user-defined
414+
/// structs.
413415
NativeType getType(Class c) {
414416
final int index = nativeTypesClasses.indexOf(c);
415417
if (index == -1) {
416418
return null;
417419
}
418420
return NativeType.values[index];
419421
}
422+
423+
/// Expression that queries VM internals at runtime to figure out on which ABI
424+
/// we are.
425+
Expression runtimeBranchOnLayout(Map<Abi, int> values) {
426+
return MethodInvocation(
427+
ConstantExpression(
428+
ListConstant(InterfaceType(intClass, Nullability.legacy), [
429+
IntConstant(values[Abi.wordSize64]),
430+
IntConstant(values[Abi.wordSize32Align32]),
431+
IntConstant(values[Abi.wordSize32Align64])
432+
]),
433+
InterfaceType(listClass, Nullability.legacy,
434+
[InterfaceType(intClass, Nullability.legacy)])),
435+
Name("[]"),
436+
Arguments([StaticInvocation(abiMethod, Arguments([]))]),
437+
listElementAt);
438+
}
420439
}
421440

422441
/// Contains all information collected by _FfiDefinitionTransformer that is

pkg/vm/lib/transformations/ffi_definitions.dart

Lines changed: 8 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -496,23 +496,6 @@ class _FfiDefinitionTransformer extends FfiTransformer {
496496
InterfaceType(pragmaClass, Nullability.nonNullable, [])));
497497
}
498498

499-
/// Expression that queries VM internals at runtime to figure out on which ABI
500-
/// we are.
501-
Expression _runtimeBranchOnLayout(Map<Abi, int> values) {
502-
return MethodInvocation(
503-
ConstantExpression(
504-
ListConstant(InterfaceType(intClass, Nullability.legacy), [
505-
IntConstant(values[Abi.wordSize64]),
506-
IntConstant(values[Abi.wordSize32Align32]),
507-
IntConstant(values[Abi.wordSize32Align64])
508-
]),
509-
InterfaceType(listClass, Nullability.legacy,
510-
[InterfaceType(intClass, Nullability.legacy)])),
511-
Name("[]"),
512-
Arguments([StaticInvocation(abiMethod, Arguments([]))]),
513-
listElementAt);
514-
}
515-
516499
Statement _generateGetterStatement(DartType dartType, NativeType type,
517500
int fileOffset, Map<Abi, int> offsets) {
518501
final bool isPointer = type == NativeType.kPointer;
@@ -558,7 +541,7 @@ class _FfiDefinitionTransformer extends FfiTransformer {
558541
addressGetter)
559542
..fileOffset = fileOffset,
560543
numAddition.name,
561-
Arguments([_runtimeBranchOnLayout(offsets)]),
544+
Arguments([runtimeBranchOnLayout(offsets)]),
562545
numAddition)
563546
], types: [
564547
dartType
@@ -594,9 +577,9 @@ class _FfiDefinitionTransformer extends FfiTransformer {
594577
typedDataOffsetInBytesGetter)
595578
..fileOffset = fileOffset,
596579
numAddition.name,
597-
Arguments([_runtimeBranchOnLayout(offsets)]),
580+
Arguments([runtimeBranchOnLayout(offsets)]),
598581
numAddition),
599-
_runtimeBranchOnLayout(lengths)
582+
runtimeBranchOnLayout(lengths)
600583
]),
601584
byteBufferAsUint8List),
602585
InterfaceType(objectClass, Nullability.nonNullable))
@@ -610,7 +593,7 @@ class _FfiDefinitionTransformer extends FfiTransformer {
610593
Arguments([
611594
PropertyGet(ThisExpression(), addressOfField.name, addressOfField)
612595
..fileOffset = fileOffset,
613-
_runtimeBranchOnLayout(offsets)
596+
runtimeBranchOnLayout(offsets)
614597
]))
615598
..fileOffset = fileOffset;
616599
if (isPointer) {
@@ -646,12 +629,12 @@ class _FfiDefinitionTransformer extends FfiTransformer {
646629
Arguments([
647630
PropertyGet(ThisExpression(), addressOfField.name, addressOfField)
648631
..fileOffset = fileOffset,
649-
_runtimeBranchOnLayout(offsets),
632+
runtimeBranchOnLayout(offsets),
650633
PropertyGet(
651634
VariableGet(argument), addressOfField.name, addressOfField)
652635
..fileOffset = fileOffset,
653636
ConstantExpression(IntConstant(0)),
654-
_runtimeBranchOnLayout(lengths),
637+
runtimeBranchOnLayout(lengths),
655638
]))
656639
..fileOffset = fileOffset);
657640
}
@@ -669,7 +652,7 @@ class _FfiDefinitionTransformer extends FfiTransformer {
669652
Arguments([
670653
PropertyGet(ThisExpression(), addressOfField.name, addressOfField)
671654
..fileOffset = fileOffset,
672-
_runtimeBranchOnLayout(offsets),
655+
runtimeBranchOnLayout(offsets),
673656
argumentExpression
674657
]))
675658
..fileOffset = fileOffset);
@@ -719,7 +702,7 @@ class _FfiDefinitionTransformer extends FfiTransformer {
719702
final Field sizeOf = Field.immutable(name,
720703
isStatic: true,
721704
isFinal: true,
722-
initializer: _runtimeBranchOnLayout(sizes),
705+
initializer: runtimeBranchOnLayout(sizes),
723706
type: InterfaceType(intClass, Nullability.legacy),
724707
fileUri: struct.fileUri,
725708
getterReference: getterReference)

pkg/vm/lib/transformations/ffi_use_sites.dart

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,15 @@ import 'package:kernel/target/targets.dart' show DiagnosticReporter;
2727
import 'package:kernel/type_environment.dart';
2828

2929
import 'ffi.dart'
30-
show FfiTransformerData, NativeType, FfiTransformer, optimizedTypes;
30+
show
31+
FfiTransformerData,
32+
NativeType,
33+
FfiTransformer,
34+
optimizedTypes,
35+
nativeTypeSizes,
36+
WORD_SIZE,
37+
UNKNOWN,
38+
wordSize;
3139

3240
/// Checks and replaces calls to dart:ffi struct fields and methods.
3341
void transformLibraries(
@@ -184,12 +192,18 @@ class _FfiUseSiteTransformer extends FfiTransformer {
184192
} else if (target == sizeOfMethod) {
185193
final DartType nativeType = node.arguments.types[0];
186194

195+
// TODO(http://dartbug.com/38721): Change this to an error after
196+
// package:ffi is no longer using sizeOf generically.
187197
if (!isFfiLibrary) {
188198
_warningNativeTypeValid(nativeType, node);
189199
}
190200

191-
// TODO(http://dartbug.com/38721): Replace calls with constant
192-
// expressions.
201+
if (nativeType is InterfaceType) {
202+
Expression inlineSizeOf = _inlineSizeOf(nativeType);
203+
if (inlineSizeOf != null) {
204+
return inlineSizeOf;
205+
}
206+
}
193207
} else if (target == lookupFunctionMethod) {
194208
final DartType nativeType = InterfaceType(
195209
nativeFunctionClass, Nullability.legacy, [node.arguments.types[0]]);
@@ -315,6 +329,28 @@ class _FfiUseSiteTransformer extends FfiTransformer {
315329
return node;
316330
}
317331

332+
Expression _inlineSizeOf(InterfaceType nativeType) {
333+
final Class nativeClass = nativeType.classNode;
334+
final NativeType nt = getType(nativeClass);
335+
if (nt == null) {
336+
// User-defined structs.
337+
Field sizeOfField = nativeClass.fields.single;
338+
return StaticGet(sizeOfField);
339+
}
340+
final int size = nativeTypeSizes[nt.index];
341+
if (size == WORD_SIZE) {
342+
return runtimeBranchOnLayout(wordSize);
343+
}
344+
if (size != UNKNOWN) {
345+
return ConstantExpression(
346+
IntConstant(size),
347+
InterfaceType(listClass, Nullability.legacy,
348+
[InterfaceType(intClass, Nullability.legacy)]));
349+
}
350+
// Size unknown.
351+
return null;
352+
}
353+
318354
// We need to replace calls to 'DynamicLibrary.lookupFunction' with explicit
319355
// Kernel, because we cannot have a generic call to 'asFunction' in its body.
320356
//

tests/ffi/sizeof_test.dart

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,19 @@ import 'dart:ffi';
88

99
import "package:expect/expect.dart";
1010

11+
import "coordinate.dart";
12+
13+
get is32Bit => 4 == sizeOf<IntPtr>();
14+
get is64Bit => 8 == sizeOf<IntPtr>();
15+
1116
void main() async {
12-
Expect.equals(true, 4 == sizeOf<Pointer>() || 8 == sizeOf<Pointer>());
17+
if (is32Bit) {
18+
Expect.equals(4, sizeOf<Pointer>());
19+
Expect.equals(20, sizeOf<Coordinate>());
20+
}
21+
if (is64Bit) {
22+
Expect.equals(8, sizeOf<Pointer>());
23+
Expect.equals(24, sizeOf<Coordinate>());
24+
}
25+
Expect.throws(() => sizeOf<Void>());
1326
}

tests/ffi_2/sizeof_test.dart

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,19 @@ import 'dart:ffi';
88

99
import "package:expect/expect.dart";
1010

11+
import "coordinate.dart";
12+
13+
get is32Bit => 4 == sizeOf<IntPtr>();
14+
get is64Bit => 8 == sizeOf<IntPtr>();
15+
1116
void main() async {
12-
Expect.equals(true, 4 == sizeOf<Pointer>() || 8 == sizeOf<Pointer>());
17+
if (is32Bit) {
18+
Expect.equals(4, sizeOf<Pointer>());
19+
Expect.equals(20, sizeOf<Coordinate>());
20+
}
21+
if (is64Bit) {
22+
Expect.equals(8, sizeOf<Pointer>());
23+
Expect.equals(24, sizeOf<Coordinate>());
24+
}
25+
Expect.throws(() => sizeOf<Void>());
1326
}

0 commit comments

Comments
 (0)