blob: e6b5e139cc8db605d3098b7d6f31df3a11c232cb [file] [log] [blame]
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:front_end/src/api_unstable/vm.dart'
show isRedirectingFactoryField;
import 'package:kernel/ast.dart';
import 'package:kernel/core_types.dart' show CoreTypes;
/// VM-specific specialization of list literals.
///
/// Transforms list literals of small length into calls to specialized
/// list constructors.
class ListLiteralsLowering {
// Number of specialized factories for list literals.
static const numSpecializedFactories = 8;
final CoreTypes coreTypes;
// Default _GrowableList(int length) factory. Used to generate empty list
// literals.
final Procedure _defaultFactory;
// Specialized _GrowableList._literalN(e1, ..., eN) factories.
final List<Procedure> _specializedFactories =
List<Procedure>.filled(numSpecializedFactories, null);
ListLiteralsLowering(this.coreTypes)
: _defaultFactory =
coreTypes.index.getMember('dart:core', '_GrowableList', '');
Procedure getSpecializedFactory(int length) =>
(_specializedFactories[length - 1] ??= coreTypes.index
.getMember('dart:core', '_GrowableList', '_literal$length'));
Expression transformListLiteral(ListLiteral node) {
if (node.isConst) {
throw 'Unexpected constant ListLiteral node'
' (such nodes should be converted to ConstantExpression): $node';
}
if (node.parent is Field && isRedirectingFactoryField(node.parent)) {
// Do not transform list literals which are used to represent
// redirecting factories.
return node;
}
final int length = node.expressions.length;
if (length == 0) {
return StaticInvocation(_defaultFactory,
Arguments([IntLiteral(0)], types: [node.typeArgument]))
..fileOffset = node.fileOffset;
} else if (length <= numSpecializedFactories) {
final factory = getSpecializedFactory(length);
return StaticInvocation(
factory, Arguments(node.expressions, types: [node.typeArgument]))
..fileOffset = node.fileOffset;
}
return node;
}
}