| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 import 'dart:typed_data'; | 5 import 'dart:typed_data'; |
| 6 import 'dart:_internal' as internal; | 6 import 'dart:_internal' as internal; |
| 7 | 7 |
| 8 // Hash table with open addressing that separates the index from keys/values. | 8 // Hash table with open addressing that separates the index from keys/values. |
| 9 | 9 |
| 10 abstract class _HashFieldBase { | 10 abstract class _HashFieldBase { |
| 11 // Each occupied entry in _index is a fixed-size integer that encodes a pair: | 11 // Each occupied entry in _index is a fixed-size integer that encodes a pair: |
| 12 // [ hash pattern for key | index of entry in _data ] | 12 // [ hash pattern for key | index of entry in _data ] |
| 13 // The hash pattern is based on hashCode, but is guaranteed to be non-zero. | 13 // The hash pattern is based on hashCode, but is guaranteed to be non-zero. |
| 14 // The length of _index is always a power of two, and there is always at | 14 // The length of _index is always a power of two, and there is always at |
| 15 // least one unoccupied entry. | 15 // least one unoccupied entry. |
| 16 // NOTE: When maps are deserialized, their _index and _hashMask is regenerated | 16 // NOTE: When maps are deserialized, their _index and _hashMask is regenerated |
| 17 // lazily by _regenerateIndex. | 17 // lazily by _regenerateIndex. |
| 18 // TODO(koda): Consider also using null _index for tiny, linear-search tables. | 18 // TODO(koda): Consider also using null _index for tiny, linear-search tables. |
| 19 Uint32List _index; | 19 Uint32List _index = new Uint32List(_HashBase._INITIAL_INDEX_SIZE); |
| 20 | 20 |
| 21 // Cached in-place mask for the hash pattern component. | 21 // Cached in-place mask for the hash pattern component. |
| 22 int _hashMask; | 22 int _hashMask = _HashBase._indexSizeToHashMask(_HashBase._INITIAL_INDEX_SIZE); |
| 23 | 23 |
| 24 // Fixed-length list of keys (set) or key/value at even/odd indices (map). | 24 // Fixed-length list of keys (set) or key/value at even/odd indices (map). |
| 25 List _data; | 25 List _data; |
| 26 | 26 |
| 27 // Length of _data that is used (i.e., keys + values for a map). | 27 // Length of _data that is used (i.e., keys + values for a map). |
| 28 int _usedData = 0; | 28 int _usedData = 0; |
| 29 | 29 |
| 30 // Number of deleted keys. | 30 // Number of deleted keys. |
| 31 int _deletedKeys = 0; | 31 int _deletedKeys = 0; |
| 32 |
| 33 // Note: All fields are initialized in a single constructor so that the VM |
| 34 // recognizes they cannot hold null values. This makes a big (20%) performance |
| 35 // difference on some operations. |
| 36 _HashFieldBase(int dataSize) : this._data = new List(dataSize); |
| 32 } | 37 } |
| 33 | 38 |
| 34 // Base class for VM-internal classes; keep in sync with _HashFieldBase. | 39 // Base class for VM-internal classes; keep in sync with _HashFieldBase. |
| 35 abstract class _HashVMBase { | 40 abstract class _HashVMBase { |
| 36 Uint32List get _index native "LinkedHashMap_getIndex"; | 41 Uint32List get _index native "LinkedHashMap_getIndex"; |
| 37 void set _index(Uint32List value) native "LinkedHashMap_setIndex"; | 42 void set _index(Uint32List value) native "LinkedHashMap_setIndex"; |
| 38 | 43 |
| 39 int get _hashMask native "LinkedHashMap_getHashMask"; | 44 int get _hashMask native "LinkedHashMap_getHashMask"; |
| 40 void set _hashMask(int value) native "LinkedHashMap_setHashMask"; | 45 void set _hashMask(int value) native "LinkedHashMap_setHashMask"; |
| 41 | 46 |
| (...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 345 new _CompactIterable<K>(this, _data, _usedData, -2, 2); | 350 new _CompactIterable<K>(this, _data, _usedData, -2, 2); |
| 346 Iterable<V> get values => | 351 Iterable<V> get values => |
| 347 new _CompactIterable<V>(this, _data, _usedData, -1, 2); | 352 new _CompactIterable<V>(this, _data, _usedData, -1, 2); |
| 348 } | 353 } |
| 349 | 354 |
| 350 class _CompactLinkedIdentityHashMap<K, V> extends _HashFieldBase | 355 class _CompactLinkedIdentityHashMap<K, V> extends _HashFieldBase |
| 351 with MapMixin<K, V>, _LinkedHashMapMixin<K, V>, _HashBase, | 356 with MapMixin<K, V>, _LinkedHashMapMixin<K, V>, _HashBase, |
| 352 _IdenticalAndIdentityHashCode | 357 _IdenticalAndIdentityHashCode |
| 353 implements LinkedHashMap<K, V> { | 358 implements LinkedHashMap<K, V> { |
| 354 | 359 |
| 355 _CompactLinkedIdentityHashMap() { | 360 _CompactLinkedIdentityHashMap() : super(_HashBase._INITIAL_INDEX_SIZE); |
| 356 _index = new Uint32List(_HashBase._INITIAL_INDEX_SIZE); | |
| 357 _hashMask = _HashBase._indexSizeToHashMask(_HashBase._INITIAL_INDEX_SIZE); | |
| 358 _data = new List(_HashBase._INITIAL_INDEX_SIZE); | |
| 359 } | |
| 360 } | 361 } |
| 361 | 362 |
| 362 class _CompactLinkedCustomHashMap<K, V> extends _HashFieldBase | 363 class _CompactLinkedCustomHashMap<K, V> extends _HashFieldBase |
| 363 with MapMixin<K, V>, _LinkedHashMapMixin<K, V>, _HashBase | 364 with MapMixin<K, V>, _LinkedHashMapMixin<K, V>, _HashBase |
| 364 implements LinkedHashMap<K, V> { | 365 implements LinkedHashMap<K, V> { |
| 365 final _equality; | 366 final _equality; |
| 366 final _hasher; | 367 final _hasher; |
| 367 final _validKey; | 368 final _validKey; |
| 368 | 369 |
| 369 // TODO(koda): Ask gbracha why I cannot have fields _equals/_hashCode. | 370 // TODO(koda): Ask gbracha why I cannot have fields _equals/_hashCode. |
| 370 int _hashCode(e) => _hasher(e); | 371 int _hashCode(e) => _hasher(e); |
| 371 bool _equals(e1, e2) => _equality(e1, e2); | 372 bool _equals(e1, e2) => _equality(e1, e2); |
| 372 | 373 |
| 373 bool containsKey(Object o) => _validKey(o) ? super.containsKey(o) : false; | 374 bool containsKey(Object o) => _validKey(o) ? super.containsKey(o) : false; |
| 374 V operator[](Object o) => _validKey(o) ? super[o] : null; | 375 V operator[](Object o) => _validKey(o) ? super[o] : null; |
| 375 V remove(Object o) => _validKey(o) ? super.remove(o) : null; | 376 V remove(Object o) => _validKey(o) ? super.remove(o) : null; |
| 376 | 377 |
| 377 _CompactLinkedCustomHashMap(this._equality, this._hasher, validKey) | 378 _CompactLinkedCustomHashMap(this._equality, this._hasher, validKey) |
| 378 : _validKey = (validKey != null) ? validKey : new _TypeTest<K>().test { | 379 : _validKey = (validKey != null) ? validKey : new _TypeTest<K>().test, |
| 379 _index = new Uint32List(_HashBase._INITIAL_INDEX_SIZE); | 380 super(_HashBase._INITIAL_INDEX_SIZE); |
| 380 _hashMask = _HashBase._indexSizeToHashMask(_HashBase._INITIAL_INDEX_SIZE); | |
| 381 _data = new List(_HashBase._INITIAL_INDEX_SIZE); | |
| 382 } | |
| 383 } | 381 } |
| 384 | 382 |
| 385 // Iterates through _data[_offset + _step], _data[_offset + 2*_step], ... | 383 // Iterates through _data[_offset + _step], _data[_offset + 2*_step], ... |
| 386 // and checks for concurrent modification. | 384 // and checks for concurrent modification. |
| 387 class _CompactIterable<E> extends IterableBase<E> { | 385 class _CompactIterable<E> extends IterableBase<E> { |
| 388 final _table; | 386 final _table; |
| 389 final List _data; | 387 final List _data; |
| 390 final int _len; | 388 final int _len; |
| 391 final int _offset; | 389 final int _offset; |
| 392 final int _step; | 390 final int _step; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 429 return false; | 427 return false; |
| 430 } | 428 } |
| 431 } | 429 } |
| 432 } | 430 } |
| 433 | 431 |
| 434 // Set implementation, analogous to _CompactLinkedHashMap. | 432 // Set implementation, analogous to _CompactLinkedHashMap. |
| 435 class _CompactLinkedHashSet<E> extends _HashFieldBase | 433 class _CompactLinkedHashSet<E> extends _HashFieldBase |
| 436 with _HashBase, _OperatorEqualsAndHashCode, SetMixin<E> | 434 with _HashBase, _OperatorEqualsAndHashCode, SetMixin<E> |
| 437 implements LinkedHashSet<E> { | 435 implements LinkedHashSet<E> { |
| 438 | 436 |
| 439 _CompactLinkedHashSet() { | 437 _CompactLinkedHashSet() : super(_HashBase._INITIAL_INDEX_SIZE >> 1) { |
| 440 assert(_HashBase._UNUSED_PAIR == 0); | 438 assert(_HashBase._UNUSED_PAIR == 0); |
| 441 _index = new Uint32List(_HashBase._INITIAL_INDEX_SIZE); | |
| 442 _hashMask = _HashBase._indexSizeToHashMask(_HashBase._INITIAL_INDEX_SIZE); | |
| 443 _data = new List(_HashBase._INITIAL_INDEX_SIZE >> 1); | |
| 444 } | 439 } |
| 445 | 440 |
| 446 int get length => _usedData - _deletedKeys; | 441 int get length => _usedData - _deletedKeys; |
| 447 | 442 |
| 448 void _rehash() { | 443 void _rehash() { |
| 449 if ((_deletedKeys << 1) > _usedData) { | 444 if ((_deletedKeys << 1) > _usedData) { |
| 450 _init(_index.length, _hashMask, _data, _usedData); | 445 _init(_index.length, _hashMask, _data, _usedData); |
| 451 } else { | 446 } else { |
| 452 _init(_index.length << 1, _hashMask >> 1, _data, _usedData); | 447 _init(_index.length << 1, _hashMask >> 1, _data, _usedData); |
| 453 } | 448 } |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 591 E lookup(Object o) => _validKey(o) ? super.lookup(o) : null; | 586 E lookup(Object o) => _validKey(o) ? super.lookup(o) : null; |
| 592 bool remove(Object o) => _validKey(o) ? super.remove(o) : false; | 587 bool remove(Object o) => _validKey(o) ? super.remove(o) : false; |
| 593 | 588 |
| 594 _CompactLinkedCustomHashSet(this._equality, this._hasher, validKey) | 589 _CompactLinkedCustomHashSet(this._equality, this._hasher, validKey) |
| 595 : _validKey = (validKey != null) ? validKey : new _TypeTest<E>().test; | 590 : _validKey = (validKey != null) ? validKey : new _TypeTest<E>().test; |
| 596 | 591 |
| 597 Set<E> toSet() => | 592 Set<E> toSet() => |
| 598 new _CompactLinkedCustomHashSet<E>(_equality, _hasher, _validKey) | 593 new _CompactLinkedCustomHashSet<E>(_equality, _hasher, _validKey) |
| 599 ..addAll(this); | 594 ..addAll(this); |
| 600 } | 595 } |
| OLD | NEW |