From 9e29d33563feaed5aa111ec5ce636dd76cf27024 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Wed, 21 Oct 2015 12:54:20 +0200 Subject: [PATCH] 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 . --- .../lib/src/cps_ir/type_mask_system.dart | 17 ++++++++++++++--- .../lib/src/cps_ir/type_propagation.dart | 4 ++-- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/pkg/compiler/lib/src/cps_ir/type_mask_system.dart b/pkg/compiler/lib/src/cps_ir/type_mask_system.dart index 2199a52146b..6910d46392d 100644 --- a/pkg/compiler/lib/src/cps_ir/type_mask_system.dart +++ b/pkg/compiler/lib/src/cps_ir/type_mask_system.dart @@ -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( - [stringType, backend.fixedArrayType, typedArray], - classWorld); + [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( + [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}) { diff --git a/pkg/compiler/lib/src/cps_ir/type_propagation.dart b/pkg/compiler/lib/src/cps_ir/type_propagation.dart index 7fd2153184a..4748a59621b 100644 --- a/pkg/compiler/lib/src/cps_ir/type_propagation.dart +++ b/pkg/compiler/lib/src/cps_ir/type_propagation.dart @@ -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);