Skip to content

Commit bf7dd1a

Browse files
committed
Document the use of two type parameters in loadUnsafe, TypedArray etc., see #349
1 parent 3c5c2ce commit bf7dd1a

File tree

6 files changed

+71
-46
lines changed

6 files changed

+71
-46
lines changed

std/assembly/internal/arraybuffer.ts

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,18 +64,40 @@ export function reallocateUnsafe(buffer: ArrayBuffer, newByteLength: i32): Array
6464
return buffer;
6565
}
6666

67-
@inline export function loadUnsafe<T,V>(buffer: ArrayBuffer, index: i32): V {
68-
return <V>load<T>(changetype<usize>(buffer) + (<usize>index << alignof<T>()), HEADER_SIZE);
67+
// The helpers below use two different types in order to emit loads and stores that load respectively
68+
// store one type to/from memory while returning/taking the desired output/input type. This allows to
69+
// emit instructions like
70+
//
71+
// * `i32.load8` ^= `<i32>load<i8>(...)` that reads an i8 but returns an i32, or
72+
// * `i64.load32_s` ^= `<i64>load<i32>(...)`) that reads a 32-bit as a 64-bit integer
73+
//
74+
// without having to emit an additional instruction for conversion purposes. This is useful for
75+
// small integers only of course. When dealing with reference types like classes, both parameters
76+
// are usually the same, even though it looks ugly.
77+
//
78+
// TODO: is there a better way to model this?
79+
80+
@inline export function loadUnsafe<T,TOut>(buffer: ArrayBuffer, index: i32): TOut {
81+
return <TOut>load<T>(changetype<usize>(buffer) + (<usize>index << alignof<T>()), HEADER_SIZE);
6982
}
7083

71-
@inline export function storeUnsafe<T,V>(buffer: ArrayBuffer, index: i32, value: V): void {
84+
@inline export function storeUnsafe<T,TIn>(buffer: ArrayBuffer, index: i32, value: TIn): void {
7285
store<T>(changetype<usize>(buffer) + (<usize>index << alignof<T>()), value, HEADER_SIZE);
7386
}
7487

75-
@inline export function loadUnsafeWithOffset<T,V>(buffer: ArrayBuffer, index: i32, byteOffset: i32): V {
76-
return <V>load<T>(changetype<usize>(buffer) + <usize>byteOffset + (<usize>index << alignof<T>()), HEADER_SIZE);
88+
@inline export function loadUnsafeWithOffset<T,TOut>(
89+
buffer: ArrayBuffer,
90+
index: i32,
91+
byteOffset: i32
92+
): TOut {
93+
return <TOut>load<T>(changetype<usize>(buffer) + <usize>byteOffset + (<usize>index << alignof<T>()), HEADER_SIZE);
7794
}
7895

79-
@inline export function storeUnsafeWithOffset<T,V>(buffer: ArrayBuffer, index: i32, value: V, byteOffset: i32): void {
96+
@inline export function storeUnsafeWithOffset<T,TIn>(
97+
buffer: ArrayBuffer,
98+
index: i32,
99+
value: TIn,
100+
byteOffset: i32
101+
): void {
80102
store<T>(changetype<usize>(buffer) + <usize>byteOffset + (<usize>index << alignof<T>()), value, HEADER_SIZE);
81103
}

std/assembly/internal/typedarray.ts

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,11 @@ import {
1212
defaultComparator
1313
} from "./array";
1414

15+
// The internal TypedArray class uses two type parameters for the same reason as `loadUnsafe` and
16+
// `storeUnsafe` in 'internal/arraybuffer.ts'. See the documentation there for details.
17+
1518
/** Typed array base class. Not a global object. */
16-
export abstract class TypedArray<T,V> {
19+
export abstract class TypedArray<T,TNative> {
1720

1821
readonly buffer: ArrayBuffer;
1922
readonly byteOffset: i32;
@@ -47,19 +50,19 @@ export abstract class TypedArray<T,V> {
4750
}
4851

4952
@operator("[]=")
50-
protected __set(index: i32, value: V): void {
53+
protected __set(index: i32, value: TNative): void {
5154
if (<u32>index >= <u32>(this.byteLength >>> alignof<T>())) throw new Error("Index out of bounds");
52-
storeUnsafeWithOffset<T,V>(this.buffer, index, value, this.byteOffset);
55+
storeUnsafeWithOffset<T,TNative>(this.buffer, index, value, this.byteOffset);
5356
}
5457

5558
@inline @operator("{}=")
56-
protected __unchecked_set(index: i32, value: V): void {
57-
storeUnsafeWithOffset<T,V>(this.buffer, index, value, this.byteOffset);
59+
protected __unchecked_set(index: i32, value: TNative): void {
60+
storeUnsafeWithOffset<T,TNative>(this.buffer, index, value, this.byteOffset);
5861
}
5962

6063
// copyWithin(target: i32, start: i32, end: i32 = this.length): this
6164

62-
fill(value: V, start: i32 = 0, end: i32 = i32.MAX_VALUE): this {
65+
fill(value: TNative, start: i32 = 0, end: i32 = i32.MAX_VALUE): this {
6366
var buffer = this.buffer;
6467
var byteOffset = this.byteOffset;
6568
var len = this.length;
@@ -75,14 +78,14 @@ export abstract class TypedArray<T,V> {
7578
}
7679
} else {
7780
for (; start < end; ++start) {
78-
storeUnsafeWithOffset<T,V>(buffer, start, value, byteOffset);
81+
storeUnsafeWithOffset<T,TNative>(buffer, start, value, byteOffset);
7982
}
8083
}
8184
return this;
8285
}
8386

8487
@inline
85-
subarray(begin: i32 = 0, end: i32 = i32.MAX_VALUE): TypedArray<T,V> {
88+
subarray(begin: i32 = 0, end: i32 = i32.MAX_VALUE): TypedArray<T,TNative> {
8689
var length = this.length;
8790
if (begin < 0) begin = max(length + begin, 0);
8891
else begin = min(begin, length);

tests/compiler/std/dataview.optimized.wat

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,7 @@
379379
if
380380
i32.const 0
381381
i32.const 8
382-
i32.const 51
382+
i32.const 54
383383
i32.const 63
384384
call $~lib/env/abort
385385
unreachable

tests/compiler/std/dataview.untouched.wat

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,7 @@
426426
if
427427
i32.const 0
428428
i32.const 8
429-
i32.const 24
429+
i32.const 27
430430
i32.const 34
431431
call $~lib/env/abort
432432
unreachable
@@ -492,7 +492,7 @@
492492
if
493493
i32.const 0
494494
i32.const 8
495-
i32.const 51
495+
i32.const 54
496496
i32.const 63
497497
call $~lib/env/abort
498498
unreachable

tests/compiler/std/typedarray.optimized.wat

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,7 @@
398398
if
399399
i32.const 0
400400
i32.const 48
401-
i32.const 24
401+
i32.const 27
402402
i32.const 34
403403
call $~lib/env/abort
404404
unreachable
@@ -442,7 +442,7 @@
442442
if
443443
i32.const 0
444444
i32.const 48
445-
i32.const 24
445+
i32.const 27
446446
i32.const 34
447447
call $~lib/env/abort
448448
unreachable
@@ -489,7 +489,7 @@
489489
if
490490
i32.const 0
491491
i32.const 48
492-
i32.const 24
492+
i32.const 27
493493
i32.const 34
494494
call $~lib/env/abort
495495
unreachable
@@ -536,7 +536,7 @@
536536
if
537537
i32.const 0
538538
i32.const 48
539-
i32.const 24
539+
i32.const 27
540540
i32.const 34
541541
call $~lib/env/abort
542542
unreachable
@@ -1015,7 +1015,7 @@
10151015
if
10161016
i32.const 0
10171017
i32.const 48
1018-
i32.const 51
1018+
i32.const 54
10191019
i32.const 63
10201020
call $~lib/env/abort
10211021
unreachable
@@ -1042,7 +1042,7 @@
10421042
if
10431043
i32.const 0
10441044
i32.const 48
1045-
i32.const 40
1045+
i32.const 43
10461046
i32.const 63
10471047
call $~lib/env/abort
10481048
unreachable
@@ -1133,7 +1133,7 @@
11331133
if
11341134
i32.const 0
11351135
i32.const 48
1136-
i32.const 51
1136+
i32.const 54
11371137
i32.const 63
11381138
call $~lib/env/abort
11391139
unreachable
@@ -1696,7 +1696,7 @@
16961696
if
16971697
i32.const 0
16981698
i32.const 48
1699-
i32.const 40
1699+
i32.const 43
17001700
i32.const 63
17011701
call $~lib/env/abort
17021702
unreachable
@@ -1720,7 +1720,7 @@
17201720
if
17211721
i32.const 0
17221722
i32.const 48
1723-
i32.const 51
1723+
i32.const 54
17241724
i32.const 63
17251725
call $~lib/env/abort
17261726
unreachable
@@ -1761,7 +1761,7 @@
17611761
if
17621762
i32.const 0
17631763
i32.const 48
1764-
i32.const 40
1764+
i32.const 43
17651765
i32.const 63
17661766
call $~lib/env/abort
17671767
unreachable
@@ -1860,7 +1860,7 @@
18601860
if
18611861
i32.const 0
18621862
i32.const 48
1863-
i32.const 40
1863+
i32.const 43
18641864
i32.const 63
18651865
call $~lib/env/abort
18661866
unreachable

tests/compiler/std/typedarray.untouched.wat

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -472,7 +472,7 @@
472472
if
473473
i32.const 0
474474
i32.const 48
475-
i32.const 24
475+
i32.const 27
476476
i32.const 34
477477
call $~lib/env/abort
478478
unreachable
@@ -537,7 +537,7 @@
537537
if
538538
i32.const 0
539539
i32.const 48
540-
i32.const 24
540+
i32.const 27
541541
i32.const 34
542542
call $~lib/env/abort
543543
unreachable
@@ -602,7 +602,7 @@
602602
if
603603
i32.const 0
604604
i32.const 48
605-
i32.const 24
605+
i32.const 27
606606
i32.const 34
607607
call $~lib/env/abort
608608
unreachable
@@ -667,7 +667,7 @@
667667
if
668668
i32.const 0
669669
i32.const 48
670-
i32.const 24
670+
i32.const 27
671671
i32.const 34
672672
call $~lib/env/abort
673673
unreachable
@@ -732,7 +732,7 @@
732732
if
733733
i32.const 0
734734
i32.const 48
735-
i32.const 24
735+
i32.const 27
736736
i32.const 34
737737
call $~lib/env/abort
738738
unreachable
@@ -797,7 +797,7 @@
797797
if
798798
i32.const 0
799799
i32.const 48
800-
i32.const 24
800+
i32.const 27
801801
i32.const 34
802802
call $~lib/env/abort
803803
unreachable
@@ -862,7 +862,7 @@
862862
if
863863
i32.const 0
864864
i32.const 48
865-
i32.const 24
865+
i32.const 27
866866
i32.const 34
867867
call $~lib/env/abort
868868
unreachable
@@ -927,7 +927,7 @@
927927
if
928928
i32.const 0
929929
i32.const 48
930-
i32.const 24
930+
i32.const 27
931931
i32.const 34
932932
call $~lib/env/abort
933933
unreachable
@@ -992,7 +992,7 @@
992992
if
993993
i32.const 0
994994
i32.const 48
995-
i32.const 24
995+
i32.const 27
996996
i32.const 34
997997
call $~lib/env/abort
998998
unreachable
@@ -1057,7 +1057,7 @@
10571057
if
10581058
i32.const 0
10591059
i32.const 48
1060-
i32.const 24
1060+
i32.const 27
10611061
i32.const 34
10621062
call $~lib/env/abort
10631063
unreachable
@@ -1675,7 +1675,7 @@
16751675
if
16761676
i32.const 0
16771677
i32.const 48
1678-
i32.const 51
1678+
i32.const 54
16791679
i32.const 63
16801680
call $~lib/env/abort
16811681
unreachable
@@ -1708,7 +1708,7 @@
17081708
if
17091709
i32.const 0
17101710
i32.const 48
1711-
i32.const 40
1711+
i32.const 43
17121712
i32.const 63
17131713
call $~lib/env/abort
17141714
unreachable
@@ -1841,7 +1841,7 @@
18411841
if
18421842
i32.const 0
18431843
i32.const 48
1844-
i32.const 51
1844+
i32.const 54
18451845
i32.const 63
18461846
call $~lib/env/abort
18471847
unreachable
@@ -2666,7 +2666,7 @@
26662666
if
26672667
i32.const 0
26682668
i32.const 48
2669-
i32.const 40
2669+
i32.const 43
26702670
i32.const 63
26712671
call $~lib/env/abort
26722672
unreachable
@@ -2700,7 +2700,7 @@
27002700
if
27012701
i32.const 0
27022702
i32.const 48
2703-
i32.const 51
2703+
i32.const 54
27042704
i32.const 63
27052705
call $~lib/env/abort
27062706
unreachable
@@ -2755,7 +2755,7 @@
27552755
if
27562756
i32.const 0
27572757
i32.const 48
2758-
i32.const 40
2758+
i32.const 43
27592759
i32.const 63
27602760
call $~lib/env/abort
27612761
unreachable
@@ -2789,7 +2789,7 @@
27892789
if
27902790
i32.const 0
27912791
i32.const 48
2792-
i32.const 51
2792+
i32.const 54
27932793
i32.const 63
27942794
call $~lib/env/abort
27952795
unreachable
@@ -2914,7 +2914,7 @@
29142914
if
29152915
i32.const 0
29162916
i32.const 48
2917-
i32.const 40
2917+
i32.const 43
29182918
i32.const 63
29192919
call $~lib/env/abort
29202920
unreachable

0 commit comments

Comments
 (0)