Skip to content

Commit 8fd8fec

Browse files
victoragnezcommit-bot@chromium.org
authored andcommitted
[vm/aot] Add support to instance calls with unboxed parameters
In order to have instance calls with unboxed parameters, all the possible targets need to be able to those parameters unboxed. Then, the methods were partitioned according to the class hierarchy, and the inferred types from TFA are used to determine the parameters that could be unboxed. This is done for non-nullable integer and double parameters, and return value. dart-aot linux x64: Bench2D 8.028% DeltaBlue 4.688% ParticleSystemPaint 27.79% Flutter release android-armv8: velocity_tracker_bench -2.026% (less is better) flutter_gallery_total_size -0.1460% flutter_gallery_instructions_size -0.2715% flutter_gallery_readonlydata_size 0.0539% Issue dart-lang/sdk#33549 Change-Id: Iedd9b4321c3d78b406ea1708e15c747754433027 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/138501 Commit-Queue: Victor Agnez Lima <victoragnez@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com> Reviewed-by: Samir Jindel <sjindel@google.com>
1 parent 2806cca commit 8fd8fec

68 files changed

Lines changed: 1238 additions & 526 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

pkg/vm/bin/dump_kernel.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import 'package:vm/metadata/procedure_attributes.dart'
1616
show ProcedureAttributesMetadataRepository;
1717
import 'package:vm/metadata/table_selector.dart'
1818
show TableSelectorMetadataRepository;
19+
import 'package:vm/metadata/unboxing_info.dart'
20+
show UnboxingInfoMetadataRepository;
1921
import 'package:vm/metadata/unreachable.dart'
2022
show UnreachableNodeMetadataRepository;
2123
import 'package:vm/metadata/call_site_attributes.dart'
@@ -42,6 +44,7 @@ main(List<String> arguments) async {
4244
component.addMetadataRepository(new InferredTypeMetadataRepository());
4345
component.addMetadataRepository(new ProcedureAttributesMetadataRepository());
4446
component.addMetadataRepository(new TableSelectorMetadataRepository());
47+
component.addMetadataRepository(new UnboxingInfoMetadataRepository());
4548
component.addMetadataRepository(new UnreachableNodeMetadataRepository());
4649
component.addMetadataRepository(new BytecodeMetadataRepository());
4750
component.addMetadataRepository(new CallSiteAttributesMetadataRepository());
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'package:kernel/ast.dart';
6+
7+
class UnboxingInfoMetadata {
8+
static const kBoxed = 0;
9+
static const kUnboxedIntCandidate = 1 << 0;
10+
static const kUnboxedDoubleCandidate = 1 << 1;
11+
static const kUnboxingCandidate =
12+
kUnboxedIntCandidate | kUnboxedDoubleCandidate;
13+
14+
final List<int> unboxedArgsInfo;
15+
int returnInfo;
16+
17+
UnboxingInfoMetadata(int argsLen) : unboxedArgsInfo = [] {
18+
for (int i = 0; i < argsLen; i++) {
19+
unboxedArgsInfo.add(kUnboxingCandidate);
20+
}
21+
returnInfo = kUnboxingCandidate;
22+
}
23+
24+
UnboxingInfoMetadata.readFromBinary(BinarySource source)
25+
: unboxedArgsInfo = List<int>.generate(
26+
source.readUInt(), (_) => source.readByte(),
27+
growable: true),
28+
returnInfo = source.readByte();
29+
30+
void writeToBinary(BinarySink sink) {
31+
sink.writeUInt30(unboxedArgsInfo.length);
32+
for (int val in unboxedArgsInfo) {
33+
sink.writeByte(val);
34+
}
35+
sink.writeByte(returnInfo);
36+
}
37+
}
38+
39+
class UnboxingInfoMetadataRepository
40+
extends MetadataRepository<UnboxingInfoMetadata> {
41+
static const repositoryTag = 'vm.unboxing-info.metadata';
42+
43+
@override
44+
final String tag = repositoryTag;
45+
46+
@override
47+
final Map<TreeNode, UnboxingInfoMetadata> mapping =
48+
<TreeNode, UnboxingInfoMetadata>{};
49+
50+
@override
51+
void writeToBinary(
52+
UnboxingInfoMetadata metadata, Node node, BinarySink sink) {
53+
metadata.writeToBinary(sink);
54+
}
55+
56+
@override
57+
UnboxingInfoMetadata readFromBinary(Node node, BinarySource source) {
58+
return UnboxingInfoMetadata.readFromBinary(source);
59+
}
60+
}

pkg/vm/lib/transformations/type_flow/transformer.dart

Lines changed: 108 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,15 @@ import 'calls.dart';
1919
import 'summary.dart';
2020
import 'table_selector.dart';
2121
import 'types.dart';
22+
import 'unboxing_info.dart';
2223
import 'utils.dart';
2324
import '../pragma.dart';
2425
import '../devirtualization.dart' show Devirtualization;
2526
import '../../metadata/direct_call.dart';
2627
import '../../metadata/inferred_type.dart';
2728
import '../../metadata/procedure_attributes.dart';
2829
import '../../metadata/table_selector.dart';
30+
import '../../metadata/unboxing_info.dart';
2931
import '../../metadata/unreachable.dart';
3032

3133
const bool kDumpClassHierarchy =
@@ -73,7 +75,12 @@ Component transformComponent(
7375
new TFADevirtualization(component, typeFlowAnalysis, hierarchy)
7476
.visitComponent(component);
7577

76-
new AnnotateKernel(component, typeFlowAnalysis).visitComponent(component);
78+
final unboxingInfo = new UnboxingInfoManager(typeFlowAnalysis);
79+
80+
_makePartition(component, typeFlowAnalysis, unboxingInfo);
81+
82+
new AnnotateKernel(component, typeFlowAnalysis, unboxingInfo)
83+
.visitComponent(component);
7784

7885
transformsStopWatch.stop();
7986

@@ -117,10 +124,13 @@ class AnnotateKernel extends RecursiveVisitor<Null> {
117124
final ProcedureAttributesMetadataRepository _procedureAttributesMetadata;
118125
final TableSelectorMetadataRepository _tableSelectorMetadata;
119126
final TableSelectorAssigner _tableSelectorAssigner;
127+
final UnboxingInfoMetadataRepository _unboxingInfoMetadata;
128+
final UnboxingInfoManager _unboxingInfo;
120129
final Class _intClass;
121130
Constant _nullConstant;
122131

123-
AnnotateKernel(Component component, this._typeFlowAnalysis)
132+
AnnotateKernel(
133+
Component component, this._typeFlowAnalysis, this._unboxingInfo)
124134
: _directCallMetadataRepository =
125135
component.metadata[DirectCallMetadataRepository.repositoryTag],
126136
_inferredTypeMetadata = new InferredTypeMetadataRepository(),
@@ -129,11 +139,13 @@ class AnnotateKernel extends RecursiveVisitor<Null> {
129139
new ProcedureAttributesMetadataRepository(),
130140
_tableSelectorMetadata = new TableSelectorMetadataRepository(),
131141
_tableSelectorAssigner = new TableSelectorAssigner(),
142+
_unboxingInfoMetadata = new UnboxingInfoMetadataRepository(),
132143
_intClass = _typeFlowAnalysis.environment.coreTypes.intClass {
133144
component.addMetadataRepository(_inferredTypeMetadata);
134145
component.addMetadataRepository(_unreachableNodeMetadata);
135146
component.addMetadataRepository(_procedureAttributesMetadata);
136147
component.addMetadataRepository(_tableSelectorMetadata);
148+
component.addMetadataRepository(_unboxingInfoMetadata);
137149
}
138150

139151
// Query whether a call site was marked as a direct call by the analysis.
@@ -301,13 +313,35 @@ class AnnotateKernel extends RecursiveVisitor<Null> {
301313
skipCheck: uncheckedParameters.contains(param));
302314
}
303315

304-
Type resultType = _typeFlowAnalysis.getSummary(member).resultType;
305-
_setInferredType(member, resultType);
316+
final unboxingInfoMetadata =
317+
_unboxingInfo.getUnboxingInfoOfMember(member);
318+
319+
if (unboxingInfoMetadata != null) {
320+
_unboxingInfoMetadata.mapping[member] = unboxingInfoMetadata;
321+
}
306322

307323
// TODO(alexmarkov): figure out how to pass receiver type.
308324
}
309325
} else if (!member.isAbstract) {
310326
_setUnreachable(member);
327+
} else if (member is! Field) {
328+
final unboxingInfoMetadata =
329+
_unboxingInfo.getUnboxingInfoOfMember(member);
330+
if (unboxingInfoMetadata != null) {
331+
// Check for partitions that only have abstract methods should be marked as boxed.
332+
if (unboxingInfoMetadata.returnInfo ==
333+
UnboxingInfoMetadata.kUnboxingCandidate) {
334+
unboxingInfoMetadata.returnInfo = UnboxingInfoMetadata.kBoxed;
335+
}
336+
for (int i = 0; i < unboxingInfoMetadata.unboxedArgsInfo.length; i++) {
337+
if (unboxingInfoMetadata.unboxedArgsInfo[i] ==
338+
UnboxingInfoMetadata.kUnboxingCandidate) {
339+
unboxingInfoMetadata.unboxedArgsInfo[i] =
340+
UnboxingInfoMetadata.kBoxed;
341+
}
342+
}
343+
_unboxingInfoMetadata.mapping[member] = unboxingInfoMetadata;
344+
}
311345
}
312346

313347
// We need to attach ProcedureAttributesMetadata to all members, even
@@ -427,6 +461,76 @@ class AnnotateKernel extends RecursiveVisitor<Null> {
427461
}
428462
}
429463

464+
// Partition the methods in order to idenfity parameters and return values
465+
// that are unboxing candidates
466+
void _makePartition(Component component, TypeFlowAnalysis typeFlowAnalysis,
467+
UnboxingInfoManager unboxingInfo) {
468+
// Traverses all the members and creates the partition graph.
469+
// Currently unboxed parameters and return value are not supported for
470+
// closures, therefore they do not exist in this graph
471+
for (bool registering in const [true, false]) {
472+
for (Library library in component.libraries) {
473+
for (Class cls in library.classes) {
474+
for (Member member in cls.members) {
475+
if (registering) {
476+
unboxingInfo.registerMember(member);
477+
} else {
478+
unboxingInfo.linkWithSuperClasses(member);
479+
}
480+
}
481+
}
482+
if (registering) {
483+
for (Member member in library.members) {
484+
unboxingInfo.registerMember(member);
485+
}
486+
}
487+
}
488+
}
489+
unboxingInfo.finishGraph();
490+
491+
for (Library library in component.libraries) {
492+
for (Class cls in library.classes) {
493+
for (Member member in cls.members) {
494+
_updateUnboxingInfoOfMember(member, typeFlowAnalysis, unboxingInfo);
495+
}
496+
}
497+
for (Member member in library.members) {
498+
_updateUnboxingInfoOfMember(member, typeFlowAnalysis, unboxingInfo);
499+
}
500+
}
501+
}
502+
503+
void _updateUnboxingInfoOfMember(Member member,
504+
TypeFlowAnalysis typeFlowAnalysis, UnboxingInfoManager unboxingInfo) {
505+
if (typeFlowAnalysis.isMemberUsed(member) && (member is! Field)) {
506+
final Args<Type> argTypes = typeFlowAnalysis.argumentTypes(member);
507+
assertx(argTypes != null);
508+
509+
final int firstParamIndex =
510+
numTypeParams(member) + (hasReceiverArg(member) ? 1 : 0);
511+
512+
final positionalParams = member.function.positionalParameters;
513+
assertx(
514+
argTypes.positionalCount == firstParamIndex + positionalParams.length);
515+
516+
for (int i = 0; i < positionalParams.length; i++) {
517+
final inferredType = argTypes.values[firstParamIndex + i];
518+
unboxingInfo.applyToArg(member, i, inferredType);
519+
}
520+
521+
final names = argTypes.names;
522+
for (int i = 0; i < names.length; i++) {
523+
final inferredType =
524+
argTypes.values[firstParamIndex + positionalParams.length + i];
525+
unboxingInfo.applyToArg(
526+
member, positionalParams.length + i, inferredType);
527+
}
528+
529+
final Type resultType = typeFlowAnalysis.getSummary(member).resultType;
530+
unboxingInfo.applyToReturn(member, resultType);
531+
}
532+
}
533+
430534
/// Tree shaking based on results of type flow analysis (TFA).
431535
///
432536
/// TFA provides information about allocated classes and reachable member

0 commit comments

Comments
 (0)