mirror of
https://github.com/dart-lang/sdk
synced 2024-09-15 21:40:07 +00:00
[dart2js] Constant-fold indexers of constant Lists and Maps
Change-Id: Id2a15047759d3b1b8230379adff314e9052c922c Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/235283 Reviewed-by: Sigmund Cherem <sigmund@google.com> Commit-Queue: Stephen Adams <sra@google.com>
This commit is contained in:
parent
641255b292
commit
6231245e80
|
@ -27,6 +27,7 @@ const greaterEqual = GreaterEqualOperation();
|
|||
const greater = GreaterOperation();
|
||||
const identity = IdentityOperation();
|
||||
const ifNull = IfNullOperation();
|
||||
const index = _IndexOperation();
|
||||
const lessEqual = LessEqualOperation();
|
||||
const less = LessOperation();
|
||||
const modulo = ModuloOperation();
|
||||
|
@ -990,6 +991,38 @@ class ToIntOperation implements UnaryOperation {
|
|||
}
|
||||
}
|
||||
|
||||
class _IndexOperation implements BinaryOperation {
|
||||
@override
|
||||
final String name = '[]';
|
||||
|
||||
const _IndexOperation();
|
||||
|
||||
@override
|
||||
ConstantValue fold(ConstantValue left, ConstantValue right) {
|
||||
if (left is ListConstantValue) {
|
||||
if (right is IntConstantValue) {
|
||||
List<ConstantValue> entries = left.entries;
|
||||
if (right.isUInt32()) {
|
||||
int index = right.intValue.toInt();
|
||||
if (index >= 0 && index < entries.length) {
|
||||
return entries[index];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (left is MapConstantValue) {
|
||||
ConstantValue value = left.lookup(right);
|
||||
if (value != null) return value;
|
||||
return const NullConstantValue();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
apply(left, right) => throw UnsupportedError('punned indexing');
|
||||
}
|
||||
|
||||
class UnfoldedUnaryOperation implements UnaryOperation {
|
||||
@override
|
||||
final String name;
|
||||
|
|
|
@ -274,6 +274,11 @@ class IndexAssignSpecializer extends InvokeDynamicSpecializer {
|
|||
class IndexSpecializer extends InvokeDynamicSpecializer {
|
||||
const IndexSpecializer();
|
||||
|
||||
@override
|
||||
constant_system.BinaryOperation operation() {
|
||||
return constant_system.index;
|
||||
}
|
||||
|
||||
@override
|
||||
HInstruction tryConvertToBuiltin(
|
||||
HInvokeDynamic instruction,
|
||||
|
|
|
@ -1493,15 +1493,15 @@ class SsaInstructionSimplifier extends HBaseVisitor
|
|||
|
||||
@override
|
||||
HInstruction visitIndex(HIndex node) {
|
||||
if (node.receiver.isConstantList() && node.index.isConstantInteger()) {
|
||||
HConstant instruction = node.receiver;
|
||||
ListConstantValue list = instruction.constant;
|
||||
List<ConstantValue> entries = list.entries;
|
||||
HConstant indexInstruction = node.index;
|
||||
IntConstantValue indexConstant = indexInstruction.constant;
|
||||
int index = indexConstant.intValue.toInt();
|
||||
if (index >= 0 && index < entries.length) {
|
||||
return _graph.addConstant(entries[index], _closedWorld);
|
||||
HInstruction receiver = node.receiver;
|
||||
if (receiver is HConstant) {
|
||||
HInstruction index = node.index;
|
||||
if (index is HConstant) {
|
||||
ConstantValue foldedValue =
|
||||
constant_system.index.fold(receiver.constant, index.constant);
|
||||
if (foldedValue != null) {
|
||||
return _graph.addConstant(foldedValue, _closedWorld);
|
||||
}
|
||||
}
|
||||
}
|
||||
return node;
|
||||
|
|
47
pkg/compiler/test/codegen/data/indexer_constant_folding.dart
Normal file
47
pkg/compiler/test/codegen/data/indexer_constant_folding.dart
Normal file
|
@ -0,0 +1,47 @@
|
|||
// Copyright (c) 2022, 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.
|
||||
|
||||
const kList = ['first', 'second'];
|
||||
const kMap = {0: 'zero', 1: 'one', 2: "two"};
|
||||
|
||||
@pragma('dart2js:noInline')
|
||||
/*member: list1:function() {
|
||||
return "second";
|
||||
}*/
|
||||
list1() {
|
||||
return kList[1]; // Constant folds to `"second"`.
|
||||
}
|
||||
|
||||
@pragma('dart2js:noInline')
|
||||
/*member: list2:function() {
|
||||
return A.ioore(B.List_first_second, 10);
|
||||
return B.List_first_second[10];
|
||||
}*/
|
||||
list2() {
|
||||
return kList[10]; // Does not constant-fold.
|
||||
}
|
||||
|
||||
@pragma('dart2js:noInline')
|
||||
/*member: map1:function() {
|
||||
return "one";
|
||||
}*/
|
||||
map1() {
|
||||
return kMap[1]; // Constant folds to `"one"`.
|
||||
}
|
||||
|
||||
@pragma('dart2js:noInline')
|
||||
/*member: map2:function() {
|
||||
return null;
|
||||
}*/
|
||||
map2() {
|
||||
return kMap[10]; // Constant folds to `null`.
|
||||
}
|
||||
|
||||
/*member: main:ignore*/
|
||||
main() {
|
||||
list1();
|
||||
list2();
|
||||
map1();
|
||||
map2();
|
||||
}
|
Loading…
Reference in a new issue