dart2js: use Es6 maps when available.

R=herhut@google.com

Review URL: https://codereview.chromium.org//1032783003

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@45105 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
floitsch@google.com 2015-04-13 14:27:25 +00:00
parent 1e264887c4
commit dbc6ae91ab
3 changed files with 78 additions and 25 deletions

View file

@ -245,6 +245,9 @@ class Namer {
// next-generation plugin, this results in starting a new Java process.
"java", "Packages", "netscape", "sun", "JavaObject", "JavaClass",
"JavaArray", "JavaMember",
// ES6 collections.
"Map",
];
static const List<String> reservedGlobalObjectNames = const <String>[

View file

@ -386,6 +386,7 @@ class _CustomHashMap<K, V> extends _HashMap<K, V> {
final _Equality<K> _equals;
final _Hasher<K> _hashCode;
final _Predicate _validKey;
_CustomHashMap(this._equals, this._hashCode, bool validKey(potentialKey))
: _validKey = (validKey != null) ? validKey : ((v) => v is K);
@ -492,7 +493,7 @@ class LinkedHashMap<K, V> {
if (isValidKey == null) {
if (hashCode == null) {
if (equals == null) {
return new JsLinkedHashMap<K, V>();
return new JsLinkedHashMap<K, V>.es6();
}
hashCode = _defaultHashCode;
} else {
@ -521,16 +522,17 @@ class LinkedHashMap<K, V> {
// Private factory constructor called by generated code for map literals.
@NoInline()
factory LinkedHashMap._literal(List keyValuePairs) {
return fillLiteralMap(keyValuePairs, new JsLinkedHashMap<K, V>());
return fillLiteralMap(keyValuePairs, new JsLinkedHashMap<K, V>.es6());
}
// Private factory constructor called by generated code for map literals.
@NoThrows() @NoInline()
factory LinkedHashMap._empty() {
return new JsLinkedHashMap<K, V>();
return new JsLinkedHashMap<K, V>.es6();
}
}
// TODO(floitsch): use ES6 Maps when available.
class _LinkedIdentityHashMap<K, V> extends JsLinkedHashMap<K, V> {
int internalComputeHashCode(var key) {
// We force the hash codes to be unsigned 30-bit integers to avoid
@ -550,10 +552,12 @@ class _LinkedIdentityHashMap<K, V> extends JsLinkedHashMap<K, V> {
}
}
// TODO(floitsch): use ES6 maps when available.
class _LinkedCustomHashMap<K, V> extends JsLinkedHashMap<K, V> {
final _Equality<K> _equals;
final _Hasher<K> _hashCode;
final _Predicate _validKey;
_LinkedCustomHashMap(this._equals, this._hashCode,
bool validKey(potentialKey))
: _validKey = (validKey != null) ? validKey : ((v) => v is K);

View file

@ -7,6 +7,8 @@
part of _js_helper;
const _USE_ES6_MAPS = const bool.fromEnvironment("dart2js.use.es6.maps");
class JsLinkedHashMap<K, V> implements LinkedHashMap<K, V>, InternalMap {
int _length = 0;
@ -32,8 +34,21 @@ class JsLinkedHashMap<K, V> implements LinkedHashMap<K, V>, InternalMap {
// iterated over.
int _modifications = 0;
static bool get _supportsEs6Maps {
return JS('returns:bool;depends:none;effects:none;',
'typeof Map != "undefined"');
}
JsLinkedHashMap();
/// If ES6 Maps are available returns a linked hash-map backed by an ES6 Map.
factory JsLinkedHashMap.es6() {
if (_USE_ES6_MAPS && JsLinkedHashMap._supportsEs6Maps) {
return new Es6LinkedHashMap<K, V>();
} else {
return new JsLinkedHashMap<K, V>();
}
}
int get length => _length;
bool get isEmpty => _length == 0;
@ -51,13 +66,11 @@ class JsLinkedHashMap<K, V> implements LinkedHashMap<K, V>, InternalMap {
if (_isStringKey(key)) {
var strings = _strings;
if (strings == null) return false;
LinkedHashMapCell cell = _getTableEntry(strings, key);
return cell != null;
return _containsTableEntry(strings, key);
} else if (_isNumericKey(key)) {
var nums = _nums;
if (nums == null) return false;
LinkedHashMapCell cell = _getTableEntry(nums, key);
return cell != null;
return _containsTableEntry(nums, key);
} else {
return internalContainsKey(key);
}
@ -124,7 +137,7 @@ class JsLinkedHashMap<K, V> implements LinkedHashMap<K, V>, InternalMap {
var rest = _rest;
if (rest == null) _rest = rest = _newHashTable();
var hash = internalComputeHashCode(key);
var bucket = JS('var', '#[#]', rest, hash);
var bucket = _getTableEntry(rest, hash);
if (bucket == null) {
LinkedHashMapCell cell = _newLinkedCell(key, value);
_setTableEntry(rest, hash, JS('var', '[#]', cell));
@ -253,7 +266,7 @@ class JsLinkedHashMap<K, V> implements LinkedHashMap<K, V>, InternalMap {
}
static bool _isStringKey(var key) {
return key is String && key != '__proto__';
return key is String;
}
static bool _isNumericKey(var key) {
@ -270,22 +283,9 @@ class JsLinkedHashMap<K, V> implements LinkedHashMap<K, V>, InternalMap {
return JS('int', '# & 0x3ffffff', key.hashCode);
}
static _getTableEntry(var table, var key) {
return JS('var', '#[#]', table, key);
}
static void _setTableEntry(var table, var key, var value) {
assert(value != null);
JS('void', '#[#] = #', table, key, value);
}
static void _deleteTableEntry(var table, var key) {
JS('void', 'delete #[#]', table, key);
}
List _getBucket(var table, var key) {
var hash = internalComputeHashCode(key);
return JS('var', '#[#]', table, hash);
return _getTableEntry(table, hash);
}
int internalFindBucketIndex(var bucket, var key) {
@ -298,7 +298,27 @@ class JsLinkedHashMap<K, V> implements LinkedHashMap<K, V>, InternalMap {
return -1;
}
static _newHashTable() {
String toString() => Maps.mapToString(this);
_getTableEntry(var table, var key) {
return JS('var', '#[#]', table, key);
}
void _setTableEntry(var table, var key, var value) {
assert(value != null);
JS('void', '#[#] = #', table, key, value);
}
void _deleteTableEntry(var table, var key) {
JS('void', 'delete #[#]', table, key);
}
bool _containsTableEntry(var table, var key) {
LinkedHashMapCell cell = _getTableEntry(table, key);
return cell != null;
}
_newHashTable() {
// Create a new JavaScript object to be used as a hash table. Use
// Object.create to avoid the properties on Object.prototype
// showing up as entries.
@ -310,8 +330,34 @@ class JsLinkedHashMap<K, V> implements LinkedHashMap<K, V>, InternalMap {
_deleteTableEntry(table, temporaryKey);
return table;
}
}
String toString() => Maps.mapToString(this);
class Es6LinkedHashMap<K, V> extends JsLinkedHashMap<K, V> {
@override
_getTableEntry(var table, var key) {
return JS('var', '#.get(#)', table, key);
}
@override
void _setTableEntry(var table, var key, var value) {
JS('void', '#.set(#, #)', table, key, value);
}
@override
void _deleteTableEntry(var table, var key) {
JS('void', '#.delete(#)', table, key);
}
@override
bool _containsTableEntry(var table, var key) {
return JS('bool', '#.has(#)', table, key);
}
@override
_newHashTable() {
return JS('var', 'new Map()');
}
}
class LinkedHashMapCell {