Version 1.4.3.
svn merge -c 37254 https://dart.googlecode.com/svn/branches/bleeding_edge branches/1.4
Update version constraints in polymer samples by applying:
https://codereview.chromium.org/330553002/
R=ricow@google.com
Review URL: https://codereview.chromium.org//338053002
git-svn-id: http://dart.googlecode.com/svn/branches/1.4@37348 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/map_tracer.dart b/sdk/lib/_internal/compiler/implementation/inferrer/map_tracer.dart
index 0e98efa..502ec95 100644
--- a/sdk/lib/_internal/compiler/implementation/inferrer/map_tracer.dart
+++ b/sdk/lib/_internal/compiler/implementation/inferrer/map_tracer.dart
@@ -79,6 +79,7 @@
// the map.
TypeInformation map = info.arguments.positional[0];
if (map is MapTypeInformation) {
+ inferrer.analyzeMapAndEnqueue(map);
mapAssignments.add(map);
} else {
// If we could select a component from a [TypeInformation],
diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart b/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart
index 46d9c59..a7ee4b5 100644
--- a/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart
+++ b/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart
@@ -1059,7 +1059,9 @@
bool analyzed = false;
// Set to false if a statically unknown key flows into this map.
- bool isDictionary = true;
+ bool _allKeysAreStrings = true;
+
+ bool get inDictionaryMode => !bailedOut && _allKeysAreStrings;
MapTypeInformation(this.initialType, this.keyType, this.valueType) {
keyType.addUser(this);
@@ -1071,13 +1073,13 @@
TypeInformation value,
[bool nonNull = false]) {
TypeInformation newInfo = null;
- if (isDictionary && key is StringLiteralTypeInformation) {
+ if (_allKeysAreStrings && key is StringLiteralTypeInformation) {
String keyString = key.asString();
typeInfoMap.putIfAbsent(keyString,
() => newInfo = new ValueInMapTypeInformation(null, nonNull));
typeInfoMap[keyString].addAssignment(value);
} else {
- isDictionary = false;
+ _allKeysAreStrings = false;
typeInfoMap.clear();
}
keyType.addAssignment(key);
@@ -1087,10 +1089,10 @@
return newInfo;
}
- List<TypeInformation> addMapAssignment(MapTypeInformation map) {
+ List<TypeInformation> addMapAssignment(MapTypeInformation other) {
List<TypeInformation> newInfos = <TypeInformation>[];
- if (map.isDictionary) {
- map.typeInfoMap.forEach((keyString, value) {
+ if (_allKeysAreStrings && other.inDictionaryMode) {
+ other.typeInfoMap.forEach((keyString, value) {
typeInfoMap.putIfAbsent(keyString, () {
TypeInformation newInfo = new ValueInMapTypeInformation(null, false);
newInfos.add(newInfo);
@@ -1098,9 +1100,12 @@
});
typeInfoMap[keyString].addAssignment(value);
});
+ } else {
+ _allKeysAreStrings = false;
+ typeInfoMap.clear();
}
- keyType.addAssignment(map.keyType);
- valueType.addAssignment(map.valueType);
+ keyType.addAssignment(other.keyType);
+ valueType.addAssignment(other.valueType);
return newInfos;
}
@@ -1119,7 +1124,7 @@
}
TypeMask toTypeMask(TypeGraphInferrerEngine inferrer) {
- if (isDictionary) {
+ if (inDictionaryMode) {
Map<String, TypeMask> mappings = new Map<String, TypeMask>();
for (var key in typeInfoMap.keys) {
mappings[key] = typeInfoMap[key].type;
@@ -1140,9 +1145,10 @@
}
TypeMask refine(TypeGraphInferrerEngine inferrer) {
- if (!bailedOut && type.isDictionary != isDictionary) {
+ if (type.isDictionary != inDictionaryMode) {
return toTypeMask(inferrer);
- } else if (!bailedOut && type.isDictionary) {
+ } else if (type.isDictionary) {
+ assert(inDictionaryMode);
DictionaryTypeMask mask = type;
for (var key in typeInfoMap.keys) {
TypeInformation value = typeInfoMap[key];
diff --git a/tests/compiler/dart2js/dictionary_types_test.dart b/tests/compiler/dart2js/dictionary_types_test.dart
index 78a59aa..b95942a 100644
--- a/tests/compiler/dart2js/dictionary_types_test.dart
+++ b/tests/compiler/dart2js/dictionary_types_test.dart
@@ -8,7 +8,7 @@
import 'compiler_helper.dart' show findElement;
var SOURCES = const {
-'testAddAll.dart': """
+'AddAll.dart': """
var dictionaryA = {'string': "aString", 'int': 42, 'double': 21.5,
'list': []};
var dictionaryB = {'string': "aString", 'int': 42, 'double': 21.5,
@@ -28,7 +28,7 @@
nullOrInt = dictionaryB['intTwo'];
}
""",
-'testUnion.dart': """
+'Union.dart': """
var dictionaryA = {'string': "aString", 'int': 42, 'double': 21.5,
'list': []};
var dictionaryB = {'string': "aString", 'intTwo': 42, 'list': []};
@@ -44,7 +44,7 @@
doubleOrNull = union['double'];
}
""",
-'testValueType.dart': """
+'ValueType.dart': """
var dictionary = {'string': "aString", 'int': 42, 'double': 21.5, 'list': []};
var keyD = 'double';
var keyI = 'int';
@@ -58,7 +58,7 @@
var x = [intOrNull, justNull];
}
""",
-'testPropagation.dart': """
+'Propagation.dart': """
class A {
A();
foo(value) {
@@ -83,28 +83,52 @@
}
print(it.foo(dictionary) + 2);
}
+""",
+'Bailout.dart': """
+ var dict = makeMap([1,2]);
+ var notInt = 0;
+ var alsoNotInt = 0;
+
+ makeMap(values) {
+ return {'moo': values[0], 'boo': values[1]};
+ }
+
+ main () {
+ dict['goo'] = 42;
+ var closure = dictfun() => dict;
+ notInt = closure()['boo'];
+ alsoNotInt = dict['goo'];
+ print("\$notInt and \$alsoNotInt.");
+ }
"""};
void main() {
asyncTest(() =>
- compileAndTest("testAddAll.dart", (types, getType, compiler) {
+ compileAndTest("AddAll.dart", (types, getType, compiler) {
Expect.equals(getType('int'), types.uint31Type);
Expect.equals(getType('anotherInt'), types.uint31Type);
Expect.equals(getType('dynamic'), types.dynamicType);
Expect.equals(getType('nullOrInt'), types.uint31Type.nullable());
- }).then((_) => compileAndTest("testUnion.dart", (types, getType, compiler) {
- Expect.equals(getType('nullOrInt'), types.uint31Type.nullable());
- Expect.isTrue(getType('aString').containsOnlyString(compiler));
- Expect.equals(getType('doubleOrNull'), types.doubleType.nullable());
- })).then((_) => compileAndTest("testValueType.dart",
- (types, getType, compiler) {
+ }));
+ asyncTest(() => compileAndTest("Union.dart", (types, getType, compiler) {
+ Expect.equals(getType('nullOrInt'), types.uint31Type.nullable());
+ Expect.isTrue(getType('aString').containsOnlyString(compiler));
+ Expect.equals(getType('doubleOrNull'), types.doubleType.nullable());
+ }));
+ asyncTest(() =>
+ compileAndTest("ValueType.dart", (types, getType, compiler) {
Expect.equals(getType('knownDouble'), types.doubleType);
Expect.equals(getType('intOrNull'), types.uint31Type.nullable());
Expect.equals(getType('justNull'), types.nullType);
- })).then((_) => compileAndTest("testPropagation.dart", (code) {
- Expect.isFalse(code.contains("J.\$add\$ns"));
- }, createCode: true))
- );
+ }));
+ asyncTest(() => compileAndTest("Propagation.dart", (code) {
+ Expect.isFalse(code.contains("J.\$add\$ns"));
+ }, createCode: true));
+ asyncTest(() => compileAndTest("Bailout.dart", (types, getType, compiler) {
+ Expect.equals(getType('notInt'), types.dynamicType);
+ Expect.equals(getType('alsoNotInt'), types.dynamicType);
+ Expect.isFalse(getType('dict').isDictionary);
+ }));
}
compileAndTest(source, checker, {createCode: false}) {
diff --git a/tools/VERSION b/tools/VERSION
index a8911eb..9ac3f12 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -26,6 +26,6 @@
CHANNEL stable
MAJOR 1
MINOR 4
-PATCH 2
+PATCH 3
PRERELEASE 0
PRERELEASE_PATCH 0