@@ -19,13 +19,15 @@ import 'calls.dart';
1919import 'summary.dart' ;
2020import 'table_selector.dart' ;
2121import 'types.dart' ;
22+ import 'unboxing_info.dart' ;
2223import 'utils.dart' ;
2324import '../pragma.dart' ;
2425import '../devirtualization.dart' show Devirtualization;
2526import '../../metadata/direct_call.dart' ;
2627import '../../metadata/inferred_type.dart' ;
2728import '../../metadata/procedure_attributes.dart' ;
2829import '../../metadata/table_selector.dart' ;
30+ import '../../metadata/unboxing_info.dart' ;
2931import '../../metadata/unreachable.dart' ;
3032
3133const 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