dart2js cps: More precise rewrite for indexables.

Strings were not sometimes not considered indexables because
[subtype=String] is not reduced to [exact=JSString].

We now rewrite the index-set operator to direct access even when the
receiver object is potentially null (but is otherwise a mutable
indexable).

BUG=
R=sra@google.com

Review URL: https://codereview.chromium.org/1420563002 .
This commit is contained in:
Asger Feldthaus
2015-10-21 12:54:20 +02:00
parent a4bfe1f1c7
commit 9e29d33563
2 changed files with 16 additions and 5 deletions
@@ -46,6 +46,8 @@ class TypeMaskSystem {
TypeMask fixedLengthType;
TypeMask interceptorType;
TypeMask _indexableTypeTest;
ClassElement get jsNullClass => backend.jsNullClass;
// TODO(karlklose): remove compiler here.
@@ -71,8 +73,17 @@ class TypeMaskSystem {
TypeMask typedArray = nonNullSubclass(backend.typedArrayClass);
fixedLengthType = new TypeMask.unionOf(
<TypeMask>[stringType, backend.fixedArrayType, typedArray],
classWorld);
<TypeMask>[stringType, backend.fixedArrayType, typedArray],
classWorld);
// Make a TypeMask containing Indexable and (redundantly) subtypes of
// string because the type inference does not infer that all strings are
// indexables.
TypeMask indexable =
new TypeMask.nonNullSubtype(backend.jsIndexableClass, classWorld);
_indexableTypeTest = new TypeMask.unionOf(
<TypeMask>[indexable, anyString],
classWorld);
}
bool methodUsesReceiverArgument(FunctionElement function) {
@@ -256,7 +267,7 @@ class TypeMaskSystem {
bool isDefinitelyIndexable(TypeMask t, {bool allowNull: false}) {
if (!allowNull && t.isNullable) return false;
return t.nonNullable().satisfies(backend.jsIndexableClass, classWorld);
return _indexableTypeTest.containsMask(t.nonNullable(), classWorld);
}
bool isDefinitelyMutableIndexable(TypeMask t, {bool allowNull: false}) {
@@ -1238,8 +1238,8 @@ class TransformingVisitor extends DeepRecursiveVisitor {
return true;
case '[]=':
if (receiverValue.isNullable) return false;
if (!typeSystem.isDefinitelyMutableIndexable(receiverValue.type)) {
if (!typeSystem.isDefinitelyMutableIndexable(receiverValue.type,
allowNull: true)) {
return false;
}
Primitive index = getDartArgument(node, 0);