Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(368)

Unified Diff: runtime/lib/compact_hash.dart

Issue 1151523002: VM-internalize the default Map implementation. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Fix fingerprints. Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/lib/collection_sources.gypi ('k') | runtime/lib/linked_hash_map.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/lib/compact_hash.dart
diff --git a/runtime/lib/compact_hash.dart b/runtime/lib/compact_hash.dart
index 9375fa882d1ba2c07ee4af52d1de4c88d1034459..22af0a23c2c7c48eaf7c5876fa841c9f9de4af0c 100644
--- a/runtime/lib/compact_hash.dart
+++ b/runtime/lib/compact_hash.dart
@@ -6,34 +6,68 @@ import 'dart:typed_data';
import 'dart:_internal' as internal;
// Hash table with open addressing that separates the index from keys/values.
-abstract class _HashBase {
+
+abstract class _HashFieldBase {
// Each occupied entry in _index is a fixed-size integer that encodes a pair:
// [ hash pattern for key | index of entry in _data ]
// The hash pattern is based on hashCode, but is guaranteed to be non-zero.
// The length of _index is always a power of two, and there is always at
// least one unoccupied entry.
- Uint32List _index;
+ Uint32List _index = new Uint32List(_HashBase._INITIAL_INDEX_SIZE);
+
+ // Cached in-place mask for the hash pattern component. On 32-bit, the top
+ // bits are wasted to avoid Mint allocation.
+ // TODO(koda): Reclaim the bits by making the compiler treat hash patterns
+ // as unsigned words.
+ int _hashMask = internal.is64Bit ?
+ (1 << (32 - _HashBase._INITIAL_INDEX_BITS)) - 1 :
+ (1 << (30 - _HashBase._INITIAL_INDEX_BITS)) - 1;
+ // Fixed-length list of keys (set) or key/value at even/odd indices (map).
+ List _data = new List(_HashBase._INITIAL_INDEX_SIZE);
+
+ // Length of _data that is used (i.e., keys + values for a map).
+ int _usedData = 0;
+
+ // Number of deleted keys.
+ int _deletedKeys = 0;
+}
+
+// Base class for VM-internal classes; keep in sync with _HashFieldBase.
+abstract class _HashVMBase {
+ Uint32List get _index native "LinkedHashMap_getIndex";
+ void set _index(Uint32List value) native "LinkedHashMap_setIndex";
+
+ int get _hashMask native "LinkedHashMap_getHashMask";
+ void set _hashMask(int value) native "LinkedHashMap_setHashMask";
+
+ List get _data native "LinkedHashMap_getData";
+ void set _data(List value) native "LinkedHashMap_setData";
+
+ int get _usedData native "LinkedHashMap_getUsedData";
+ void set _usedData(int value) native "LinkedHashMap_setUsedData";
+
+ int get _deletedKeys native "LinkedHashMap_getDeletedKeys";
+ void set _deletedKeys(int value) native "LinkedHashMap_setDeletedKeys";
+}
+
+// This mixin can be applied to _HashFieldBase or _HashVMBase (for
+// normal and VM-internalized classes, respectivley), which provide the
+// actual fields/accessors that this mixin assumes.
+// TODO(koda): Consider moving field comments to _HashFieldBase.
+abstract class _HashBase {
// The number of bits used for each component is determined by table size.
// The length of _index is twice the number of entries in _data, and both
// are doubled when _data is full. Thus, _index will have a max load factor
// of 1/2, which enables one more bit to be used for the hash.
- // TODO(koda): Consider growing _data by factor sqrt(2), twice as often.
+ // TODO(koda): Consider growing _data by factor sqrt(2), twice as often.
static const int _INITIAL_INDEX_BITS = 3;
static const int _INITIAL_INDEX_SIZE = 1 << (_INITIAL_INDEX_BITS + 1);
-
+
// Unused and deleted entries are marked by 0 and 1, respectively.
static const int _UNUSED_PAIR = 0;
static const int _DELETED_PAIR = 1;
-
- // Cached in-place mask for the hash pattern component. On 32-bit, the top
- // bits are wasted to avoid Mint allocation.
- // TODO(koda): Reclaim the bits by making the compiler treat hash patterns
- // as unsigned words.
- int _hashMask = internal.is64Bit ?
- (1 << (32 - _INITIAL_INDEX_BITS)) - 1 :
- (1 << (30 - _INITIAL_INDEX_BITS)) - 1;
-
+
static int _hashPattern(int fullHash, int hashMask, int size) {
final int maskedHash = fullHash & hashMask;
// TODO(koda): Consider keeping bit length and use left shift.
@@ -47,14 +81,7 @@ abstract class _HashBase {
return ((i << 1) + i) & sizeMask;
}
static int _nextProbe(int i, int sizeMask) => (i + 1) & sizeMask;
-
- // Fixed-length list of keys (set) or key/value at even/odd indices (map).
- List _data;
- // Length of _data that is used (i.e., keys + values for a map).
- int _usedData = 0;
- // Number of deleted keys.
- int _deletedKeys = 0;
-
+
// A self-loop is used to mark a deleted key or value.
static bool _isDeleted(List data, Object keyOrValue) =>
identical(keyOrValue, data);
@@ -79,22 +106,19 @@ class _IdenticalAndIdentityHashCode {
bool _equals(e1, e2) => identical(e1, e2);
}
-// Map with iteration in insertion order (hence "Linked"). New keys are simply
-// appended to _data.
-class _CompactLinkedHashMap<K, V>
- extends MapBase<K, V> with _HashBase, _OperatorEqualsAndHashCode
+// VM-internalized implementation of a default-constructed LinkedHashMap.
+class _InternalLinkedHashMap<K, V> extends _HashVMBase
+ with MapMixin<K, V>, _LinkedHashMapMixin<K, V>, _HashBase,
+ _OperatorEqualsAndHashCode
implements LinkedHashMap<K, V> {
+ factory _InternalLinkedHashMap() native "LinkedHashMap_allocate";
+}
- _CompactLinkedHashMap() {
- assert(_HashBase._UNUSED_PAIR == 0);
- _index = new Uint32List(_HashBase._INITIAL_INDEX_SIZE);
- _data = new List(_HashBase._INITIAL_INDEX_SIZE);
- }
-
+class _LinkedHashMapMixin<K, V> {
int get length => (_usedData >> 1) - _deletedKeys;
bool get isEmpty => length == 0;
bool get isNotEmpty => !isEmpty;
-
+
void _rehash() {
if ((_deletedKeys << 2) > _usedData) {
// TODO(koda): Consider shrinking.
@@ -105,7 +129,7 @@ class _CompactLinkedHashMap<K, V>
_init(_index.length << 1, _hashMask >> 1, _data, _usedData);
}
}
-
+
void clear() {
if (!isEmpty) {
_init(_index.length, _hashMask);
@@ -131,7 +155,7 @@ class _CompactLinkedHashMap<K, V>
}
}
}
-
+
void _insert(K key, V value, int hashPattern, int i) {
if (_usedData == _data.length) {
_rehash();
@@ -145,7 +169,7 @@ class _CompactLinkedHashMap<K, V>
_data[_usedData++] = value;
}
}
-
+
// If key is present, returns the index of the value in _data, else returns
// the negated insertion point in _index.
int _findValueOrInsertPoint(K key, int fullHash, int hashPattern, int size) {
@@ -173,7 +197,7 @@ class _CompactLinkedHashMap<K, V>
}
return firstDeleted >= 0 ? -firstDeleted : -i;
}
-
+
void operator[]=(K key, V value) {
final int size = _index.length;
final int sizeMask = size - 1;
@@ -187,7 +211,7 @@ class _CompactLinkedHashMap<K, V>
_insert(key, value, hashPattern, i);
}
}
-
+
V putIfAbsent(K key, V ifAbsent()) {
final int size = _index.length;
final int sizeMask = size - 1;
@@ -210,7 +234,7 @@ class _CompactLinkedHashMap<K, V>
}
return value;
}
-
+
V remove(Object key) {
final int size = _index.length;
final int sizeMask = size - 1;
@@ -239,7 +263,7 @@ class _CompactLinkedHashMap<K, V>
}
return null;
}
-
+
// If key is absent, return _data (which is never a value).
Object _getValueOrData(Object key) {
final int size = _index.length;
@@ -264,14 +288,14 @@ class _CompactLinkedHashMap<K, V>
}
return _data;
}
-
+
bool containsKey(Object key) => !identical(_data, _getValueOrData(key));
-
+
V operator[](Object key) {
var v = _getValueOrData(key);
return identical(_data, v) ? null : v;
}
-
+
bool containsValue(Object value) {
for (var v in values) {
// Spec. says this should always use "==", also for identity maps, etc.
@@ -297,12 +321,15 @@ class _CompactLinkedHashMap<K, V>
new _CompactIterable<V>(this, _data, _usedData, -1, 2);
}
-class _CompactLinkedIdentityHashMap<K, V>
- extends _CompactLinkedHashMap<K, V> with _IdenticalAndIdentityHashCode {
+class _CompactLinkedIdentityHashMap<K, V> extends _HashFieldBase
+ with MapMixin<K, V>, _LinkedHashMapMixin<K, V>, _HashBase,
+ _IdenticalAndIdentityHashCode
+ implements LinkedHashMap<K, V> {
}
-class _CompactLinkedCustomHashMap<K, V>
- extends _CompactLinkedHashMap<K, V> {
+class _CompactLinkedCustomHashMap<K, V> extends _HashFieldBase
+ with MapMixin<K, V>, _LinkedHashMapMixin<K, V>, _HashBase
+ implements LinkedHashMap<K, V> {
final _equality;
final _hasher;
final _validKey;
@@ -369,8 +396,8 @@ class _CompactIterator<E> implements Iterator<E> {
}
// Set implementation, analogous to _CompactLinkedHashMap.
-class _CompactLinkedHashSet<E>
- extends SetBase<E> with _HashBase, _OperatorEqualsAndHashCode
+class _CompactLinkedHashSet<E> extends _HashFieldBase
+ with _HashBase, _OperatorEqualsAndHashCode, SetMixin<E>
implements LinkedHashSet<E> {
_CompactLinkedHashSet() {
« no previous file with comments | « runtime/lib/collection_sources.gypi ('k') | runtime/lib/linked_hash_map.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698