Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions NOTICE
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ under the licensing terms detailed in LICENSE:
* Fabián Heredia Montiel <[email protected]>
* Jonas Minnberg <[email protected]>
* Kam Chehresa <[email protected]>
* Pebrian <[email protected]>

Portions of this software are derived from third-party works licensed under
the following terms:
Expand Down
10 changes: 9 additions & 1 deletion std/assembly/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2394,7 +2394,7 @@ interface NewableFunction extends Function {
interface IArguments {}
interface RegExp {}

declare class Map<K,V> {
interface Map<K, V> {
readonly size: i32;
has(key: K): bool;
set(key: K, value: V): this;
Expand All @@ -2406,6 +2406,14 @@ declare class Map<K,V> {
toString(): string;
}

type MapInitialEntries<K, V> = {key: K, value: V}[]

interface MapConstructor {
new <K, V>(entries?: MapInitialEntries<K, V> | null): Map<K, V>;
}

declare const Map: MapConstructor;

declare class Set<K> {
readonly size: i32;
has(value: K): bool;
Expand Down
45 changes: 43 additions & 2 deletions std/assembly/map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,13 @@ function ENTRY_SIZE<K,V>(): usize {
return size;
}

class KeyValue<K,V> {
key: K;
value: V;
}

export type MapInitialEntries<K,V> = KeyValue<K,V>[];

export class Map<K,V> {

// buckets referencing their respective first entry, usize[bucketsMask + 1]
Expand All @@ -66,8 +73,42 @@ export class Map<K,V> {
private entriesOffset: i32 = 0;
private entriesCount: i32 = 0;

constructor() {
/* nop */
constructor(initialEntries: MapInitialEntries<K,V> | null = null) {
if (initialEntries) {
Copy link
Member

@MaxGraey MaxGraey Aug 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just use early return:

Suggested change
if (initialEntries) {
if (!initialEntries || !initialEntries.length) return;

This will reduce one level of ident

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My bad for suggesting that

if (initialEntries.length >= this.entriesCapacity) this.bucketsMask = initialEntries.length;
this.rehash((this.bucketsMask << 1) | 1);

for (let i = 0; i < initialEntries.length; i++) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

plz cache initialEntries.length into var

let key = initialEntries[i].key;
let value = initialEntries[i].value;
let hashCode = HASH<K>(key);
let entry = this.find(key, hashCode); // unmanaged!
if (entry) {
entry.value = value;
if (isManaged<V>()) {
__link(changetype<usize>(this), changetype<usize>(value), true);
}
} else {
// append new entry
let entries = this.entries;
let entry = changetype<MapEntry<K,V>>(changetype<usize>(entries) + <usize>(this.entriesOffset++) * ENTRY_SIZE<K,V>());
// link with the map
entry.key = key;
if (isManaged<K>()) {
__link(changetype<usize>(this), changetype<usize>(key), true);
}
entry.value = value;
if (isManaged<V>()) {
__link(changetype<usize>(this), changetype<usize>(value), true);
}
++this.entriesCount;
// link with previous entry in bucket
let bucketPtrBase = changetype<usize>(this.buckets) + <usize>(hashCode & this.bucketsMask) * BUCKET_SIZE;
entry.taggedNext = load<usize>(bucketPtrBase);
store<usize>(bucketPtrBase, changetype<usize>(entry));
}
}
}
}

get size(): i32 {
Expand Down
72 changes: 13 additions & 59 deletions tests/compiler/rt/flags.debug.wat
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@
(global $rt/flags/VALUE_ALIGN_REF i32 (i32.const 256))
(global $rt/flags/KEY_ALIGN_REF i32 (i32.const 131072))
(global $~lib/rt/__rtti_base i32 (i32.const 176))
(global $~lib/memory/__data_end i32 (i32.const 392))
(global $~lib/memory/__stack_pointer (mut i32) (i32.const 33160))
(global $~lib/memory/__heap_base i32 (i32.const 33160))
(global $~lib/memory/__data_end i32 (i32.const 456))
(global $~lib/memory/__stack_pointer (mut i32) (i32.const 33224))
(global $~lib/memory/__heap_base i32 (i32.const 33224))
(memory $0 1)
(data $0 (i32.const 12) "<\00\00\00\00\00\00\00\00\00\00\00\02\00\00\00$\00\00\00I\00n\00d\00e\00x\00 \00o\00u\00t\00 \00o\00f\00 \00r\00a\00n\00g\00e\00\00\00\00\00\00\00\00\00")
(data $1 (i32.const 76) ",\00\00\00\00\00\00\00\00\00\00\00\02\00\00\00\14\00\00\00~\00l\00i\00b\00/\00r\00t\00.\00t\00s\00\00\00\00\00\00\00\00\00")
(data $2 (i32.const 124) ",\00\00\00\00\00\00\00\00\00\00\00\02\00\00\00\16\00\00\00r\00t\00/\00f\00l\00a\00g\00s\00.\00t\00s\00\00\00\00\00\00\00")
(data $3 (i32.const 176) "5\00\00\00 \00\00\00 \00\00\00 \00\00\00\00\00\00\00A\08\00\00A\00\00\00A\00\00\00\81\08\00\00\81\00\00\00\01\t\00\00\01\01\00\00\01\n\00\00\01\02\00\00\01\19\00\00\01\1a\00\00B\08\00\00B\00\00\00\82\08\00\00\82\00\00\00\02\t\00\00\02\01\00\00\02\n\00\00\02\02\00\00\02\19\00\00\02\1a\00\00\02\04\00\00 \00\00\00\02A\00\00\02a\00\00H\08\00\00H\00\00\00\88\08\00\00\88\00\00\00\08\t\00\00\08\01\00\00\08\n\00\00\08\02\00\00\08\19\00\00\08\1a\00\00\08\04\00\00\08A\00\00\08a\00\00P\08\08\00\90\08\14\00\10\t\12\00\10\n\11\00\10\84\10\00P\08\82\00P\08\c2\00\10\c1\10\00\10\e1\10\00\10a\c2\00\10\t2\00")
(data $3 (i32.const 176) "E\00\00\00 \00\00\00 \00\00\00 \00\00\00\00\00\00\00A\08\00\00A\00\00\00A\00\00\00\81\08\00\00\81\00\00\00\01\t\00\00\01\01\00\00\01\n\00\00\01\02\00\00\01\19\00\00\01\1a\00\00B\08\00\00B\00\00\00\82\08\00\00\82\00\00\00\02\t\00\00\02\01\00\00\02\n\00\00\02\02\00\00\02\19\00\00\02\1a\00\00\02\04\00\00 \00\00\00\02A\00\00\02a\00\00H\08\00\00H\00\00\00\88\08\00\00\88\00\00\00\08\t\00\00\08\01\00\00\08\n\00\00\08\02\00\00\08\19\00\00\08\1a\00\00\08\04\00\00\08A\00\00\08a\00\00\90\08\14\00 \00\00\00\02A\00\00\10\t\12\00 \00\00\00\02A\00\00\10\n\11\00 \00\00\00\02A\00\00P\08\82\00\00\00\00\00\02A\00\00P\08\c2\00\00\00\00\00\02A\00\00\10\c1\10\00\00\00\00\00\02A\00\00\10\e1\10\00\00\00\00\00\02A\00\00\10a\c2\00\00\00\00\00\02A\00\00\10\t2\00 \00\00\00\02A\00\00")
(table $0 1 1 funcref)
(elem $0 (i32.const 1))
(export "memory" (memory $0))
Expand Down Expand Up @@ -607,23 +607,8 @@
unreachable
end
)
(func $"rt/flags/test<~lib/map/Map<v128,i8>>" (param $flags i32)
i32.const 42
call $~lib/rt/__typeinfo
local.get $flags
i32.eq
i32.eqz
if
i32.const 0
i32.const 144
i32.const 6
i32.const 3
call $~lib/builtins/abort
unreachable
end
)
(func $"rt/flags/test<~lib/map/Map<i64,i16>>" (param $flags i32)
i32.const 43
i32.const 42
call $~lib/rt/__typeinfo
local.get $flags
i32.eq
Expand All @@ -638,21 +623,6 @@
end
)
(func $"rt/flags/test<~lib/map/Map<i32,i32>>" (param $flags i32)
i32.const 44
call $~lib/rt/__typeinfo
local.get $flags
i32.eq
i32.eqz
if
i32.const 0
i32.const 144
i32.const 6
i32.const 3
call $~lib/builtins/abort
unreachable
end
)
(func $"rt/flags/test<~lib/map/Map<i16,i64>>" (param $flags i32)
i32.const 45
call $~lib/rt/__typeinfo
local.get $flags
Expand All @@ -667,8 +637,8 @@
unreachable
end
)
(func $"rt/flags/test<~lib/map/Map<i8,v128>>" (param $flags i32)
i32.const 46
(func $"rt/flags/test<~lib/map/Map<i16,i64>>" (param $flags i32)
i32.const 48
call $~lib/rt/__typeinfo
local.get $flags
i32.eq
Expand All @@ -683,7 +653,7 @@
end
)
(func $"rt/flags/test<~lib/map/Map<rt/flags/Ref,i8>>" (param $flags i32)
i32.const 47
i32.const 51
call $~lib/rt/__typeinfo
local.get $flags
i32.eq
Expand All @@ -698,7 +668,7 @@
end
)
(func $"rt/flags/test<~lib/map/Map<rt/flags/Ref|null,i8>>" (param $flags i32)
i32.const 48
i32.const 54
call $~lib/rt/__typeinfo
local.get $flags
i32.eq
Expand All @@ -713,7 +683,7 @@
end
)
(func $"rt/flags/test<~lib/map/Map<i8,rt/flags/Ref>>" (param $flags i32)
i32.const 49
i32.const 57
call $~lib/rt/__typeinfo
local.get $flags
i32.eq
Expand All @@ -728,7 +698,7 @@
end
)
(func $"rt/flags/test<~lib/map/Map<i8,rt/flags/Ref|null>>" (param $flags i32)
i32.const 50
i32.const 60
call $~lib/rt/__typeinfo
local.get $flags
i32.eq
Expand All @@ -743,7 +713,7 @@
end
)
(func $"rt/flags/test<~lib/map/Map<rt/flags/Ref|null,rt/flags/Ref|null>>" (param $flags i32)
i32.const 51
i32.const 63
call $~lib/rt/__typeinfo
local.get $flags
i32.eq
Expand All @@ -758,7 +728,7 @@
end
)
(func $"rt/flags/test<~lib/map/Map<f32,i32>>" (param $flags i32)
i32.const 52
i32.const 66
call $~lib/rt/__typeinfo
local.get $flags
i32.eq
Expand Down Expand Up @@ -982,14 +952,6 @@
i32.or
call $rt/flags/test<~lib/set/Set<rt/flags/Ref|null>>
i32.const 16
i32.const 524288
i32.or
i32.const 64
i32.or
i32.const 2048
i32.or
call $"rt/flags/test<~lib/map/Map<v128,i8>>"
i32.const 16
i32.const 262144
i32.or
i32.const 1048576
Expand Down Expand Up @@ -1020,14 +982,6 @@
i32.or
call $"rt/flags/test<~lib/map/Map<i16,i64>>"
i32.const 16
i32.const 32768
i32.or
i32.const 1048576
i32.or
i32.const 1024
i32.or
call $"rt/flags/test<~lib/map/Map<i8,v128>>"
i32.const 16
global.get $rt/flags/KEY_ALIGN_REF
i32.or
i32.const 8388608
Expand Down
28 changes: 9 additions & 19 deletions tests/compiler/rt/flags.release.wat
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
(data $1.1 (i32.const 1112) "\02\00\00\00\14\00\00\00~\00l\00i\00b\00/\00r\00t\00.\00t\00s")
(data $2 (i32.const 1148) ",")
(data $2.1 (i32.const 1160) "\02\00\00\00\16\00\00\00r\00t\00/\00f\00l\00a\00g\00s\00.\00t\00s")
(data $3 (i32.const 1200) "5\00\00\00 \00\00\00 \00\00\00 \00\00\00\00\00\00\00A\08\00\00A\00\00\00A\00\00\00\81\08\00\00\81\00\00\00\01\t\00\00\01\01\00\00\01\n\00\00\01\02\00\00\01\19\00\00\01\1a\00\00B\08\00\00B\00\00\00\82\08\00\00\82\00\00\00\02\t\00\00\02\01\00\00\02\n\00\00\02\02\00\00\02\19\00\00\02\1a\00\00\02\04\00\00 \00\00\00\02A\00\00\02a\00\00H\08\00\00H\00\00\00\88\08\00\00\88\00\00\00\08\t\00\00\08\01\00\00\08\n\00\00\08\02\00\00\08\19\00\00\08\1a\00\00\08\04\00\00\08A\00\00\08a\00\00P\08\08\00\90\08\14\00\10\t\12\00\10\n\11\00\10\84\10\00P\08\82\00P\08\c2\00\10\c1\10\00\10\e1\10\00\10a\c2\00\10\t2")
(data $3 (i32.const 1200) "E\00\00\00 \00\00\00 \00\00\00 \00\00\00\00\00\00\00A\08\00\00A\00\00\00A\00\00\00\81\08\00\00\81\00\00\00\01\t\00\00\01\01\00\00\01\n\00\00\01\02\00\00\01\19\00\00\01\1a\00\00B\08\00\00B\00\00\00\82\08\00\00\82\00\00\00\02\t\00\00\02\01\00\00\02\n\00\00\02\02\00\00\02\19\00\00\02\1a\00\00\02\04\00\00 \00\00\00\02A\00\00\02a\00\00H\08\00\00H\00\00\00\88\08\00\00\88\00\00\00\08\t\00\00\08\01\00\00\08\n\00\00\08\02\00\00\08\19\00\00\08\1a\00\00\08\04\00\00\08A\00\00\08a\00\00\90\08\14\00 \00\00\00\02A\00\00\10\t\12\00 \00\00\00\02A\00\00\10\n\11\00 \00\00\00\02A\00\00P\08\82\00\00\00\00\00\02A\00\00P\08\c2\00\00\00\00\00\02A\00\00\10\c1\10\00\00\00\00\00\02A\00\00\10\e1\10\00\00\00\00\00\02A\00\00\10a\c2\00\00\00\00\00\02A\00\00\10\t2\00 \00\00\00\02A")
(export "memory" (memory $0))
(start $~start)
(func $~lib/rt/__typeinfo (param $0 i32) (result i32)
Expand Down Expand Up @@ -222,55 +222,45 @@
br_if $folding-inner0
i32.const 42
call $~lib/rt/__typeinfo
i32.const 526416
i32.ne
br_if $folding-inner0
i32.const 43
call $~lib/rt/__typeinfo
i32.const 1312912
i32.ne
br_if $folding-inner0
i32.const 44
i32.const 45
call $~lib/rt/__typeinfo
i32.const 1181968
i32.ne
br_if $folding-inner0
i32.const 45
i32.const 48
call $~lib/rt/__typeinfo
i32.const 1116688
i32.ne
br_if $folding-inner0
i32.const 46
call $~lib/rt/__typeinfo
i32.const 1082384
i32.ne
br_if $folding-inner0
i32.const 47
i32.const 51
call $~lib/rt/__typeinfo
i32.const 8521808
i32.ne
br_if $folding-inner0
i32.const 48
i32.const 54
call $~lib/rt/__typeinfo
i32.const 12716112
i32.ne
br_if $folding-inner0
i32.const 49
i32.const 57
call $~lib/rt/__typeinfo
i32.const 1098000
i32.ne
br_if $folding-inner0
i32.const 50
i32.const 60
call $~lib/rt/__typeinfo
i32.const 1106192
i32.ne
br_if $folding-inner0
i32.const 51
i32.const 63
call $~lib/rt/__typeinfo
i32.const 12738832
i32.ne
br_if $folding-inner0
i32.const 52
i32.const 66
call $~lib/rt/__typeinfo
i32.const 3279120
i32.ne
Expand Down
4 changes: 2 additions & 2 deletions tests/compiler/rt/flags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,11 @@ test<Set<v128>>(TypeinfoFlags.SET | TypeinfoFlags.VALUE_ALIGN_4);
test<Set<Ref>>(TypeinfoFlags.SET | VALUE_ALIGN_REF | TypeinfoFlags.VALUE_MANAGED);
test<Set<Ref | null>>(TypeinfoFlags.SET | VALUE_ALIGN_REF | TypeinfoFlags.VALUE_NULLABLE | TypeinfoFlags.VALUE_MANAGED);

test<Map<v128,i8>>(TypeinfoFlags.MAP | TypeinfoFlags.KEY_ALIGN_4 | TypeinfoFlags.VALUE_ALIGN_0 | TypeinfoFlags.VALUE_SIGNED);
// test<Map<v128,i8>>(TypeinfoFlags.MAP | TypeinfoFlags.KEY_ALIGN_4 | TypeinfoFlags.VALUE_ALIGN_0 | TypeinfoFlags.VALUE_SIGNED);
test<Map<i64,i16>>(TypeinfoFlags.MAP | TypeinfoFlags.KEY_ALIGN_3 | TypeinfoFlags.KEY_SIGNED | TypeinfoFlags.VALUE_ALIGN_1 | TypeinfoFlags.VALUE_SIGNED);
test<Map<i32,i32>>(TypeinfoFlags.MAP | TypeinfoFlags.KEY_ALIGN_2 | TypeinfoFlags.KEY_SIGNED | TypeinfoFlags.VALUE_ALIGN_2 | TypeinfoFlags.VALUE_SIGNED);
test<Map<i16,i64>>(TypeinfoFlags.MAP | TypeinfoFlags.KEY_ALIGN_1 | TypeinfoFlags.KEY_SIGNED | TypeinfoFlags.VALUE_ALIGN_3 | TypeinfoFlags.VALUE_SIGNED);
test<Map<i8,v128>>(TypeinfoFlags.MAP | TypeinfoFlags.KEY_ALIGN_0 | TypeinfoFlags.KEY_SIGNED | TypeinfoFlags.VALUE_ALIGN_4);
// test<Map<i8,v128>>(TypeinfoFlags.MAP | TypeinfoFlags.KEY_ALIGN_0 | TypeinfoFlags.KEY_SIGNED | TypeinfoFlags.VALUE_ALIGN_4);
test<Map<Ref,i8>>(TypeinfoFlags.MAP | KEY_ALIGN_REF | TypeinfoFlags.KEY_MANAGED | TypeinfoFlags.VALUE_ALIGN_0 | TypeinfoFlags.VALUE_SIGNED);
test<Map<Ref | null,i8>>(TypeinfoFlags.MAP | KEY_ALIGN_REF | TypeinfoFlags.KEY_NULLABLE | TypeinfoFlags.KEY_MANAGED | TypeinfoFlags.VALUE_ALIGN_0 | TypeinfoFlags.VALUE_SIGNED);
test<Map<i8,Ref>>(TypeinfoFlags.MAP | TypeinfoFlags.KEY_ALIGN_0 | TypeinfoFlags.KEY_SIGNED | TypeinfoFlags.VALUE_MANAGED | VALUE_ALIGN_REF);
Expand Down
Loading
Loading