Skip to content

Commit

Permalink
Document the use of two type parameters in loadUnsafe, TypedArray etc…
Browse files Browse the repository at this point in the history
  • Loading branch information
dcodeIO authored and Willem Wyndham committed Dec 26, 2018
1 parent 1c969f1 commit b7f9ba1
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 46 deletions.
34 changes: 28 additions & 6 deletions std/assembly/internal/arraybuffer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,18 +64,40 @@ export function reallocateUnsafe(buffer: ArrayBuffer, newByteLength: i32): Array
return buffer;
}

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

@inline export function loadUnsafe<T,TOut>(buffer: ArrayBuffer, index: i32): TOut {
return <TOut>load<T>(changetype<usize>(buffer) + (<usize>index << alignof<T>()), HEADER_SIZE);
}

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

@inline export function loadUnsafeWithOffset<T,V>(buffer: ArrayBuffer, index: i32, byteOffset: i32): V {
return <V>load<T>(changetype<usize>(buffer) + <usize>byteOffset + (<usize>index << alignof<T>()), HEADER_SIZE);
@inline export function loadUnsafeWithOffset<T,TOut>(
buffer: ArrayBuffer,
index: i32,
byteOffset: i32
): TOut {
return <TOut>load<T>(changetype<usize>(buffer) + <usize>byteOffset + (<usize>index << alignof<T>()), HEADER_SIZE);
}

@inline export function storeUnsafeWithOffset<T,V>(buffer: ArrayBuffer, index: i32, value: V, byteOffset: i32): void {
@inline export function storeUnsafeWithOffset<T,TIn>(
buffer: ArrayBuffer,
index: i32,
value: TIn,
byteOffset: i32
): void {
store<T>(changetype<usize>(buffer) + <usize>byteOffset + (<usize>index << alignof<T>()), value, HEADER_SIZE);
}
19 changes: 11 additions & 8 deletions std/assembly/internal/typedarray.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,11 @@ import {
defaultComparator
} from "./array";

// The internal TypedArray class uses two type parameters for the same reason as `loadUnsafe` and
// `storeUnsafe` in 'internal/arraybuffer.ts'. See the documentation there for details.

/** Typed array base class. Not a global object. */
export abstract class TypedArray<T,V> {
export abstract class TypedArray<T,TNative> {

readonly buffer: ArrayBuffer;
readonly byteOffset: i32;
Expand Down Expand Up @@ -47,19 +50,19 @@ export abstract class TypedArray<T,V> {
}

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

@inline @operator("{}=")
protected __unchecked_set(index: i32, value: V): void {
storeUnsafeWithOffset<T,V>(this.buffer, index, value, this.byteOffset);
protected __unchecked_set(index: i32, value: TNative): void {
storeUnsafeWithOffset<T,TNative>(this.buffer, index, value, this.byteOffset);
}

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

fill(value: V, start: i32 = 0, end: i32 = i32.MAX_VALUE): this {
fill(value: TNative, start: i32 = 0, end: i32 = i32.MAX_VALUE): this {
var buffer = this.buffer;
var byteOffset = this.byteOffset;
var len = this.length;
Expand All @@ -75,14 +78,14 @@ export abstract class TypedArray<T,V> {
}
} else {
for (; start < end; ++start) {
storeUnsafeWithOffset<T,V>(buffer, start, value, byteOffset);
storeUnsafeWithOffset<T,TNative>(buffer, start, value, byteOffset);
}
}
return this;
}

@inline
subarray(begin: i32 = 0, end: i32 = i32.MAX_VALUE): TypedArray<T,V> {
subarray(begin: i32 = 0, end: i32 = i32.MAX_VALUE): TypedArray<T,TNative> {
var length = this.length;
if (begin < 0) begin = max(length + begin, 0);
else begin = min(begin, length);
Expand Down
2 changes: 1 addition & 1 deletion tests/compiler/std/dataview.optimized.wat
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@
if
i32.const 0
i32.const 8
i32.const 51
i32.const 54
i32.const 63
call $~lib/env/abort
unreachable
Expand Down
4 changes: 2 additions & 2 deletions tests/compiler/std/dataview.untouched.wat
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,7 @@
if
i32.const 0
i32.const 8
i32.const 24
i32.const 27
i32.const 34
call $~lib/env/abort
unreachable
Expand Down Expand Up @@ -492,7 +492,7 @@
if
i32.const 0
i32.const 8
i32.const 51
i32.const 54
i32.const 63
call $~lib/env/abort
unreachable
Expand Down
22 changes: 11 additions & 11 deletions tests/compiler/std/typedarray.optimized.wat
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,7 @@
if
i32.const 0
i32.const 48
i32.const 24
i32.const 27
i32.const 34
call $~lib/env/abort
unreachable
Expand Down Expand Up @@ -442,7 +442,7 @@
if
i32.const 0
i32.const 48
i32.const 24
i32.const 27
i32.const 34
call $~lib/env/abort
unreachable
Expand Down Expand Up @@ -489,7 +489,7 @@
if
i32.const 0
i32.const 48
i32.const 24
i32.const 27
i32.const 34
call $~lib/env/abort
unreachable
Expand Down Expand Up @@ -536,7 +536,7 @@
if
i32.const 0
i32.const 48
i32.const 24
i32.const 27
i32.const 34
call $~lib/env/abort
unreachable
Expand Down Expand Up @@ -1015,7 +1015,7 @@
if
i32.const 0
i32.const 48
i32.const 51
i32.const 54
i32.const 63
call $~lib/env/abort
unreachable
Expand All @@ -1042,7 +1042,7 @@
if
i32.const 0
i32.const 48
i32.const 40
i32.const 43
i32.const 63
call $~lib/env/abort
unreachable
Expand Down Expand Up @@ -1133,7 +1133,7 @@
if
i32.const 0
i32.const 48
i32.const 51
i32.const 54
i32.const 63
call $~lib/env/abort
unreachable
Expand Down Expand Up @@ -1696,7 +1696,7 @@
if
i32.const 0
i32.const 48
i32.const 40
i32.const 43
i32.const 63
call $~lib/env/abort
unreachable
Expand All @@ -1720,7 +1720,7 @@
if
i32.const 0
i32.const 48
i32.const 51
i32.const 54
i32.const 63
call $~lib/env/abort
unreachable
Expand Down Expand Up @@ -1761,7 +1761,7 @@
if
i32.const 0
i32.const 48
i32.const 40
i32.const 43
i32.const 63
call $~lib/env/abort
unreachable
Expand Down Expand Up @@ -1860,7 +1860,7 @@
if
i32.const 0
i32.const 48
i32.const 40
i32.const 43
i32.const 63
call $~lib/env/abort
unreachable
Expand Down
36 changes: 18 additions & 18 deletions tests/compiler/std/typedarray.untouched.wat
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,7 @@
if
i32.const 0
i32.const 48
i32.const 24
i32.const 27
i32.const 34
call $~lib/env/abort
unreachable
Expand Down Expand Up @@ -537,7 +537,7 @@
if
i32.const 0
i32.const 48
i32.const 24
i32.const 27
i32.const 34
call $~lib/env/abort
unreachable
Expand Down Expand Up @@ -602,7 +602,7 @@
if
i32.const 0
i32.const 48
i32.const 24
i32.const 27
i32.const 34
call $~lib/env/abort
unreachable
Expand Down Expand Up @@ -667,7 +667,7 @@
if
i32.const 0
i32.const 48
i32.const 24
i32.const 27
i32.const 34
call $~lib/env/abort
unreachable
Expand Down Expand Up @@ -732,7 +732,7 @@
if
i32.const 0
i32.const 48
i32.const 24
i32.const 27
i32.const 34
call $~lib/env/abort
unreachable
Expand Down Expand Up @@ -797,7 +797,7 @@
if
i32.const 0
i32.const 48
i32.const 24
i32.const 27
i32.const 34
call $~lib/env/abort
unreachable
Expand Down Expand Up @@ -862,7 +862,7 @@
if
i32.const 0
i32.const 48
i32.const 24
i32.const 27
i32.const 34
call $~lib/env/abort
unreachable
Expand Down Expand Up @@ -927,7 +927,7 @@
if
i32.const 0
i32.const 48
i32.const 24
i32.const 27
i32.const 34
call $~lib/env/abort
unreachable
Expand Down Expand Up @@ -992,7 +992,7 @@
if
i32.const 0
i32.const 48
i32.const 24
i32.const 27
i32.const 34
call $~lib/env/abort
unreachable
Expand Down Expand Up @@ -1057,7 +1057,7 @@
if
i32.const 0
i32.const 48
i32.const 24
i32.const 27
i32.const 34
call $~lib/env/abort
unreachable
Expand Down Expand Up @@ -1675,7 +1675,7 @@
if
i32.const 0
i32.const 48
i32.const 51
i32.const 54
i32.const 63
call $~lib/env/abort
unreachable
Expand Down Expand Up @@ -1708,7 +1708,7 @@
if
i32.const 0
i32.const 48
i32.const 40
i32.const 43
i32.const 63
call $~lib/env/abort
unreachable
Expand Down Expand Up @@ -1841,7 +1841,7 @@
if
i32.const 0
i32.const 48
i32.const 51
i32.const 54
i32.const 63
call $~lib/env/abort
unreachable
Expand Down Expand Up @@ -2666,7 +2666,7 @@
if
i32.const 0
i32.const 48
i32.const 40
i32.const 43
i32.const 63
call $~lib/env/abort
unreachable
Expand Down Expand Up @@ -2700,7 +2700,7 @@
if
i32.const 0
i32.const 48
i32.const 51
i32.const 54
i32.const 63
call $~lib/env/abort
unreachable
Expand Down Expand Up @@ -2755,7 +2755,7 @@
if
i32.const 0
i32.const 48
i32.const 40
i32.const 43
i32.const 63
call $~lib/env/abort
unreachable
Expand Down Expand Up @@ -2789,7 +2789,7 @@
if
i32.const 0
i32.const 48
i32.const 51
i32.const 54
i32.const 63
call $~lib/env/abort
unreachable
Expand Down Expand Up @@ -2914,7 +2914,7 @@
if
i32.const 0
i32.const 48
i32.const 40
i32.const 43
i32.const 63
call $~lib/env/abort
unreachable
Expand Down

0 comments on commit b7f9ba1

Please sign in to comment.