Skip to content

Commit 5d0ecdd

Browse files
committed
fix: use early return in Map constructor, correct conditional logic and use cache initialEntries length
1 parent bcd86f2 commit 5d0ecdd

File tree

6 files changed

+8980
-7993
lines changed

6 files changed

+8980
-7993
lines changed

std/assembly/map.ts

Lines changed: 33 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -74,39 +74,40 @@ export class Map<K,V> {
7474
private entriesCount: i32 = 0;
7575

7676
constructor(initialEntries: MapInitialEntries<K,V> | null = null) {
77-
if (initialEntries) {
78-
if (initialEntries.length >= this.entriesCapacity) this.bucketsMask = initialEntries.length;
79-
this.rehash((this.bucketsMask << 1) | 1);
80-
81-
for (let i = 0; i < initialEntries.length; i++) {
82-
let key = initialEntries[i].key;
83-
let value = initialEntries[i].value;
84-
let hashCode = HASH<K>(key);
85-
let entry = this.find(key, hashCode); // unmanaged!
86-
if (entry) {
87-
entry.value = value;
88-
if (isManaged<V>()) {
89-
__link(changetype<usize>(this), changetype<usize>(value), true);
90-
}
91-
} else {
92-
// append new entry
93-
let entries = this.entries;
94-
let entry = changetype<MapEntry<K,V>>(changetype<usize>(entries) + <usize>(this.entriesOffset++) * ENTRY_SIZE<K,V>());
95-
// link with the map
96-
entry.key = key;
97-
if (isManaged<K>()) {
98-
__link(changetype<usize>(this), changetype<usize>(key), true);
99-
}
100-
entry.value = value;
101-
if (isManaged<V>()) {
102-
__link(changetype<usize>(this), changetype<usize>(value), true);
103-
}
104-
++this.entriesCount;
105-
// link with previous entry in bucket
106-
let bucketPtrBase = changetype<usize>(this.buckets) + <usize>(hashCode & this.bucketsMask) * BUCKET_SIZE;
107-
entry.taggedNext = load<usize>(bucketPtrBase);
108-
store<usize>(bucketPtrBase, changetype<usize>(entry));
77+
if (!initialEntries || !initialEntries.length) return this;
78+
let initialEntriesLength = initialEntries.length;
79+
80+
if (initialEntriesLength >= this.entriesCapacity) this.bucketsMask = initialEntriesLength;
81+
this.rehash((this.bucketsMask << 1) | 1);
82+
83+
for (let i = 0; i < initialEntriesLength; i++) {
84+
let key = initialEntries[i].key;
85+
let value = initialEntries[i].value;
86+
let hashCode = HASH<K>(key);
87+
let entry = this.find(key, hashCode); // unmanaged!
88+
if (entry) {
89+
entry.value = value;
90+
if (isManaged<V>()) {
91+
__link(changetype<usize>(this), changetype<usize>(value), true);
92+
}
93+
} else {
94+
// append new entry
95+
let entries = this.entries;
96+
let entry = changetype<MapEntry<K,V>>(changetype<usize>(entries) + <usize>(this.entriesOffset++) * ENTRY_SIZE<K,V>());
97+
// link with the map
98+
entry.key = key;
99+
if (isManaged<K>()) {
100+
__link(changetype<usize>(this), changetype<usize>(key), true);
101+
}
102+
entry.value = value;
103+
if (isManaged<V>()) {
104+
__link(changetype<usize>(this), changetype<usize>(value), true);
109105
}
106+
++this.entriesCount;
107+
// link with previous entry in bucket
108+
let bucketPtrBase = changetype<usize>(this.buckets) + <usize>(hashCode & this.bucketsMask) * BUCKET_SIZE;
109+
entry.taggedNext = load<usize>(bucketPtrBase);
110+
store<usize>(bucketPtrBase, changetype<usize>(entry));
110111
}
111112
}
112113
}

0 commit comments

Comments
 (0)