Skip to content

Commit c77c272

Browse files
alexmarkovcommit-bot@chromium.org
authored andcommitted
[vm,aot,bytecode] Handle inferred-type metadata when generating bytecode
Change-Id: Ifadb25c782db5c95025e7275daf0676abd73cf49 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/120341 Reviewed-by: Régis Crelier <regis@google.com> Commit-Queue: Alexander Markov <alexmarkov@google.com>
1 parent 59e00e6 commit c77c272

File tree

7 files changed

+262
-46
lines changed

7 files changed

+262
-46
lines changed

pkg/vm/lib/bytecode/gen_bytecode.dart

Lines changed: 122 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ import 'source_positions.dart' show LineStarts, SourcePositions;
5656
import '../metadata/bytecode.dart';
5757
import '../metadata/direct_call.dart'
5858
show DirectCallMetadata, DirectCallMetadataRepository;
59+
import '../metadata/inferred_type.dart'
60+
show InferredType, InferredTypeMetadataRepository;
5961
import '../metadata/procedure_attributes.dart'
6062
show ProcedureAttributesMetadata, ProcedureAttributesMetadataRepository;
6163

@@ -126,6 +128,8 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
126128
Map<TreeNode, DirectCallMetadata> directCallMetadata;
127129
ProcedureAttributesMetadataRepository procedureAttributesMetadataRepository;
128130
ProcedureAttributesMetadata procedureAttributesMetadata;
131+
Map<TreeNode, InferredType> inferredTypeMetadata;
132+
List<Constant> inferredTypesAttribute;
129133

130134
List<ClassDeclaration> classDeclarations;
131135
List<FieldDeclaration> fieldDeclarations;
@@ -182,6 +186,9 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
182186

183187
procedureAttributesMetadataRepository =
184188
component.metadata[ProcedureAttributesMetadataRepository.repositoryTag];
189+
190+
inferredTypeMetadata = component
191+
.metadata[InferredTypeMetadataRepository.repositoryTag]?.mapping;
185192
}
186193

187194
@override
@@ -410,17 +417,23 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
410417
}
411418

412419
ObjectHandle getMemberAttributes(Member member) {
413-
if (procedureAttributesMetadata == null) {
420+
if (procedureAttributesMetadata == null && inferredTypesAttribute == null) {
414421
return null;
415422
}
416-
final procedureAttributes = procedureAttributesMetadataRepository
417-
.getBytecodeAttribute(procedureAttributesMetadata);
418423
// List of pairs (tag, value).
419-
final attrs = ListConstant(const DynamicType(), <Constant>[
420-
StringConstant(ProcedureAttributesMetadataRepository.repositoryTag),
421-
procedureAttributes,
422-
]);
423-
return objectTable.getHandle(attrs);
424+
final attrs = <Constant>[];
425+
if (procedureAttributesMetadata != null) {
426+
final attribute = procedureAttributesMetadataRepository
427+
.getBytecodeAttribute(procedureAttributesMetadata);
428+
attrs.add(
429+
StringConstant(ProcedureAttributesMetadataRepository.repositoryTag));
430+
attrs.add(attribute);
431+
}
432+
if (inferredTypesAttribute != null) {
433+
attrs.add(StringConstant(InferredTypeMetadataRepository.repositoryTag));
434+
attrs.add(ListConstant(const DynamicType(), inferredTypesAttribute));
435+
}
436+
return objectTable.getHandle(ListConstant(const DynamicType(), attrs));
424437
}
425438

426439
// Insert annotations for the function and its parameters into the annotations
@@ -1180,15 +1193,18 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
11801193
bool isSet: false,
11811194
bool isDynamicForwarder: false,
11821195
bool isUnchecked: false,
1183-
TreeNode context}) {
1196+
TreeNode node}) {
11841197
assert(!isGet || !isSet);
11851198
final kind = isGet
11861199
? InvocationKind.getter
11871200
: (isSet ? InvocationKind.setter : InvocationKind.method);
11881201
final cpIndex = cp.addDirectCall(kind, target, argDesc, isDynamicForwarder);
11891202

11901203
if (totalArgCount >= argumentsLimit) {
1191-
throw new TooManyArgumentsException(context.fileOffset);
1204+
throw new TooManyArgumentsException(node.fileOffset);
1205+
}
1206+
if (inferredTypeMetadata != null && node != null) {
1207+
_appendInferredType(node, asm.offset);
11921208
}
11931209
if (isUnchecked) {
11941210
asm.emitUncheckedDirectCall(cpIndex, totalArgCount);
@@ -1201,7 +1217,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
12011217
{bool hasReceiver: false,
12021218
bool isFactory: false,
12031219
bool isUnchecked: false,
1204-
TreeNode context}) {
1220+
TreeNode node}) {
12051221
final argDesc = objectTable.getArgDescHandleByArguments(args,
12061222
hasReceiver: hasReceiver, isFactory: isFactory);
12071223

@@ -1216,7 +1232,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
12161232
}
12171233

12181234
_genDirectCall(target, argDesc, totalArgCount,
1219-
isUnchecked: isUnchecked, context: context);
1235+
isUnchecked: isUnchecked, node: node);
12201236
}
12211237

12221238
void _genTypeArguments(List<DartType> typeArgs, {Class instantiatingClass}) {
@@ -1553,6 +1569,28 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
15531569
procedureAttributesMetadata = procedureAttributesMetadataRepository != null
15541570
? procedureAttributesMetadataRepository.mapping[node]
15551571
: null;
1572+
1573+
if (inferredTypeMetadata != null) {
1574+
if (node is Field) {
1575+
// Field type is at PC = -1.
1576+
_appendInferredType(node, -1);
1577+
} else if (enclosingFunction != null && hasCode) {
1578+
assert(node is Procedure || node is Constructor);
1579+
// Parameter types are at PC = -N,..,-1 where N - number of declared
1580+
// (explicit) parameters.
1581+
int i = -(enclosingFunction.positionalParameters.length +
1582+
enclosingFunction.namedParameters.length);
1583+
for (var v in enclosingFunction.positionalParameters) {
1584+
_appendInferredType(v, i);
1585+
++i;
1586+
}
1587+
for (var v in enclosingFunction.namedParameters) {
1588+
_appendInferredType(v, i);
1589+
++i;
1590+
}
1591+
}
1592+
}
1593+
15561594
if (!hasCode) {
15571595
return;
15581596
}
@@ -1596,6 +1634,32 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
15961634
_genEqualsOperatorNullHandling(node);
15971635
}
15981636

1637+
void _appendInferredType(TreeNode node, int pc) {
1638+
final InferredType md = inferredTypeMetadata[node];
1639+
if (md == null) {
1640+
return;
1641+
}
1642+
inferredTypesAttribute ??= <Constant>[];
1643+
// List of triplets (PC, concreteClass, flags).
1644+
// Verify that PCs are monotonically increasing.
1645+
assert(inferredTypesAttribute.isEmpty ||
1646+
(inferredTypesAttribute[inferredTypesAttribute.length - 3]
1647+
as IntConstant)
1648+
.value <
1649+
pc);
1650+
inferredTypesAttribute.add(IntConstant(pc));
1651+
Class concreteClass = md.concreteClass;
1652+
// VM uses more specific function type and doesn't expect to
1653+
// see inferred _Closure class.
1654+
if (concreteClass != null && concreteClass != closureClass) {
1655+
inferredTypesAttribute
1656+
.add(TypeLiteralConstant(coreTypes.legacyRawType(concreteClass)));
1657+
} else {
1658+
inferredTypesAttribute.add(NullConstant());
1659+
}
1660+
inferredTypesAttribute.add(IntConstant(md.flags));
1661+
}
1662+
15991663
// Generate additional code for 'operator ==' to handle nulls.
16001664
void _genEqualsOperatorNullHandling(Member member) {
16011665
if (member.name.name != '==' ||
@@ -1693,6 +1757,8 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
16931757
savedAssemblers = null;
16941758
hasErrors = false;
16951759
procedureAttributesMetadata = null;
1760+
inferredTypeMetadata = null;
1761+
inferredTypesAttribute = null;
16961762
}
16971763

16981764
SourcePositions finalizeSourcePositions() {
@@ -2767,7 +2833,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
27672833
new Arguments(node.arguments.positional, named: node.arguments.named)
27682834
..parent = node;
27692835
_genArguments(null, args);
2770-
_genDirectCallWithArgs(node.target, args, hasReceiver: true, context: node);
2836+
_genDirectCallWithArgs(node.target, args, hasReceiver: true, node: node);
27712837
asm.emitDrop1();
27722838
}
27732839

@@ -2777,7 +2843,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
27772843
_genArguments(node.receiver, args);
27782844
final target = node.target;
27792845
if (target is Procedure && !target.isGetter && !target.isSetter) {
2780-
_genDirectCallWithArgs(target, args, hasReceiver: true, context: node);
2846+
_genDirectCallWithArgs(target, args, hasReceiver: true, node: node);
27812847
} else {
27822848
throw new UnsupportedOperationError(
27832849
'Unsupported DirectMethodInvocation with target ${target.runtimeType} $target');
@@ -2789,7 +2855,8 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
27892855
_generateNode(node.receiver);
27902856
final target = node.target;
27912857
if (target is Field || (target is Procedure && target.isGetter)) {
2792-
_genDirectCall(target, objectTable.getArgDescHandle(1), 1, isGet: true);
2858+
_genDirectCall(target, objectTable.getArgDescHandle(1), 1,
2859+
isGet: true, node: node);
27932860
} else {
27942861
throw new UnsupportedOperationError(
27952862
'Unsupported DirectPropertyGet with ${target.runtimeType} $target');
@@ -2810,7 +2877,8 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
28102877

28112878
final target = node.target;
28122879
assert(target is Field || (target is Procedure && target.isSetter));
2813-
_genDirectCall(target, objectTable.getArgDescHandle(2), 2, isSet: true);
2880+
_genDirectCall(target, objectTable.getArgDescHandle(2), 2,
2881+
isSet: true, node: node);
28142882
asm.emitDrop1();
28152883

28162884
if (hasResult) {
@@ -3031,7 +3099,14 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
30313099
asm.emitSpecializedBytecode(opcode);
30323100
}
30333101

3102+
bool _isUncheckedCall(
3103+
Node node, Member interfaceTarget, Expression receiver) =>
3104+
isUncheckedCall(interfaceTarget, receiver, typeEnvironment) ||
3105+
(inferredTypeMetadata != null &&
3106+
inferredTypeMetadata[node]?.skipCheck == true);
3107+
30343108
void _genInstanceCall(
3109+
Node node,
30353110
InvocationKind invocationKind,
30363111
Member interfaceTarget,
30373112
Name targetName,
@@ -3040,7 +3115,11 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
30403115
ObjectHandle argDesc) {
30413116
final isDynamic = interfaceTarget == null;
30423117
final isUnchecked = invocationKind != InvocationKind.getter &&
3043-
isUncheckedCall(interfaceTarget, receiver, typeEnvironment);
3118+
_isUncheckedCall(node, interfaceTarget, receiver);
3119+
3120+
if (inferredTypeMetadata != null) {
3121+
_appendInferredType(node, asm.offset);
3122+
}
30443123

30453124
if (invocationKind != InvocationKind.getter && !isDynamic && !isUnchecked) {
30463125
final staticReceiverType = getStaticType(receiver, typeEnvironment);
@@ -3118,11 +3197,13 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
31183197
if (directCall != null) {
31193198
final isDynamicForwarder = (interfaceTarget == null);
31203199
final isUnchecked =
3121-
isUncheckedCall(interfaceTarget, node.receiver, typeEnvironment);
3200+
_isUncheckedCall(node, interfaceTarget, node.receiver);
31223201
_genDirectCall(directCall.target, argDesc, totalArgCount,
3123-
isDynamicForwarder: isDynamicForwarder, isUnchecked: isUnchecked);
3202+
isDynamicForwarder: isDynamicForwarder,
3203+
isUnchecked: isUnchecked,
3204+
node: node);
31243205
} else {
3125-
_genInstanceCall(InvocationKind.method, interfaceTarget, node.name,
3206+
_genInstanceCall(node, InvocationKind.method, interfaceTarget, node.name,
31263207
node.receiver, totalArgCount, argDesc);
31273208
}
31283209
}
@@ -3142,10 +3223,10 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
31423223
asm.emitCheckReceiverForNull(
31433224
cp.addSelectorName(node.name, InvocationKind.getter));
31443225
}
3145-
_genDirectCall(directCall.target, argDesc, 1, isGet: true);
3226+
_genDirectCall(directCall.target, argDesc, 1, isGet: true, node: node);
31463227
} else {
3147-
_genInstanceCall(InvocationKind.getter, node.interfaceTarget, node.name,
3148-
node.receiver, 1, argDesc);
3228+
_genInstanceCall(node, InvocationKind.getter, node.interfaceTarget,
3229+
node.name, node.receiver, 1, argDesc);
31493230
}
31503231
}
31513232

@@ -3178,14 +3259,15 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
31783259
if (directCall != null) {
31793260
final isDynamicForwarder = (node.interfaceTarget == null);
31803261
final isUnchecked =
3181-
isUncheckedCall(node.interfaceTarget, node.receiver, typeEnvironment);
3262+
_isUncheckedCall(node, node.interfaceTarget, node.receiver);
31823263
_genDirectCall(directCall.target, argDesc, numArguments,
31833264
isSet: true,
31843265
isDynamicForwarder: isDynamicForwarder,
3185-
isUnchecked: isUnchecked);
3266+
isUnchecked: isUnchecked,
3267+
node: node);
31863268
} else {
3187-
_genInstanceCall(InvocationKind.setter, node.interfaceTarget, node.name,
3188-
node.receiver, numArguments, argDesc);
3269+
_genInstanceCall(node, InvocationKind.setter, node.interfaceTarget,
3270+
node.name, node.receiver, numArguments, argDesc);
31893271
}
31903272

31913273
asm.emitDrop1();
@@ -3214,7 +3296,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
32143296
}
32153297
_genArguments(new ThisExpression(), args);
32163298
_genDirectCallWithArgs(target, args,
3217-
hasReceiver: true, isUnchecked: true, context: node);
3299+
hasReceiver: true, isUnchecked: true, node: node);
32183300
}
32193301

32203302
@override
@@ -3228,7 +3310,8 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
32283310
return;
32293311
}
32303312
_genPushReceiver();
3231-
_genDirectCall(target, objectTable.getArgDescHandle(1), 1, isGet: true);
3313+
_genDirectCall(target, objectTable.getArgDescHandle(1), 1,
3314+
isGet: true, node: node);
32323315
}
32333316

32343317
@override
@@ -3252,7 +3335,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
32523335

32533336
assert(target is Field || (target is Procedure && target.isSetter));
32543337
_genDirectCall(target, objectTable.getArgDescHandle(2), 2,
3255-
isSet: true, isUnchecked: true);
3338+
isSet: true, isUnchecked: true, node: node);
32563339
}
32573340

32583341
asm.emitDrop1();
@@ -3321,11 +3404,13 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
33213404
} else if (_hasTrivialInitializer(target)) {
33223405
asm.emitLoadStatic(cp.addStaticField(target));
33233406
} else {
3324-
_genDirectCall(target, objectTable.getArgDescHandle(0), 0, isGet: true);
3407+
_genDirectCall(target, objectTable.getArgDescHandle(0), 0,
3408+
isGet: true, node: node);
33253409
}
33263410
} else if (target is Procedure) {
33273411
if (target.isGetter) {
3328-
_genDirectCall(target, objectTable.getArgDescHandle(0), 0, isGet: true);
3412+
_genDirectCall(target, objectTable.getArgDescHandle(0), 0,
3413+
isGet: true, node: node);
33293414
} else if (target.isFactory || target.isRedirectingFactoryConstructor) {
33303415
throw 'Unexpected target for StaticGet: factory $target';
33313416
} else {
@@ -3367,7 +3452,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
33673452
}
33683453
_genArguments(null, args);
33693454
_genDirectCallWithArgs(target, args,
3370-
isFactory: target.isFactory, context: node);
3455+
isFactory: target.isFactory, node: node);
33713456
}
33723457

33733458
@override
@@ -3389,7 +3474,8 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
33893474
int cpIndex = cp.addStaticField(target);
33903475
asm.emitStoreStaticTOS(cpIndex);
33913476
} else {
3392-
_genDirectCall(target, objectTable.getArgDescHandle(1), 1, isSet: true);
3477+
_genDirectCall(target, objectTable.getArgDescHandle(1), 1,
3478+
isSet: true, node: node);
33933479
asm.emitDrop1();
33943480
}
33953481
}
@@ -4242,7 +4328,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
42424328
final args = node.arguments;
42434329
assert(args.types.isEmpty);
42444330
_genArguments(new ThisExpression(), args);
4245-
_genDirectCallWithArgs(node.target, args, hasReceiver: true, context: node);
4331+
_genDirectCallWithArgs(node.target, args, hasReceiver: true, node: node);
42464332
asm.emitDrop1();
42474333
}
42484334

@@ -4260,7 +4346,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
42604346
}
42614347
}
42624348
assert(target != null);
4263-
_genDirectCallWithArgs(target, args, hasReceiver: true, context: node);
4349+
_genDirectCallWithArgs(target, args, hasReceiver: true, node: node);
42644350
asm.emitDrop1();
42654351
}
42664352

pkg/vm/lib/metadata/inferred_type.dart

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ class InferredType {
4747
bool get isInt => (_flags & flagInt) != 0;
4848
bool get skipCheck => (_flags & flagSkipCheck) != 0;
4949

50+
int get flags => _flags;
51+
5052
@override
5153
String toString() {
5254
final base =
@@ -65,8 +67,10 @@ class InferredType {
6567

6668
/// Repository for [InferredType].
6769
class InferredTypeMetadataRepository extends MetadataRepository<InferredType> {
70+
static const String repositoryTag = 'vm.inferred-type.metadata';
71+
6872
@override
69-
final String tag = 'vm.inferred-type.metadata';
73+
String get tag => repositoryTag;
7074

7175
@override
7276
final Map<TreeNode, InferredType> mapping = <TreeNode, InferredType>{};

0 commit comments

Comments
 (0)