From e78c4c7f544fc4958ebcf7819b0cc1835731afb8 Mon Sep 17 00:00:00 2001 From: dcode Date: Wed, 13 Mar 2019 03:09:24 +0100 Subject: [PATCH] more --- std/assembly/array.ts | 97 ++++++++++++++++++++-------------- std/assembly/runtime.ts | 24 ++++----- std/assembly/string.ts | 10 ++-- std/assembly/typedarray.ts | 105 ++++++++++++++++++++++++++----------- std/assembly/vector.ts | 3 +- 5 files changed, 149 insertions(+), 90 deletions(-) diff --git a/std/assembly/array.ts b/std/assembly/array.ts index 3811d5a6..22f9d236 100644 --- a/std/assembly/array.ts +++ b/std/assembly/array.ts @@ -40,6 +40,10 @@ export class Array extends ArrayBufferView { this.length_ = length; } + @unsafe get buffer(): ArrayBuffer { + return this.data; + } + get length(): i32 { return this.length_; } @@ -49,18 +53,18 @@ export class Array extends ArrayBufferView { this.length_ = length; } - resize(length: i32): void { - var buffer = this.buffer; - var oldCapacity = buffer.byteLength >>> alignof(); + private resize(length: i32): void { + var oldData = this.data; + var oldCapacity = oldData.byteLength >>> alignof(); if (length > oldCapacity) { const MAX_LENGTH = ArrayBuffer.MAX_BYTELENGTH >>> alignof(); if (length > MAX_LENGTH) throw new RangeError("Invalid array length"); - let newCapacity = length << alignof(); - let newBuffer = REALLOC(changetype(buffer), newCapacity); - if (newBuffer !== changetype(buffer)) { - this.buffer = changetype(newBuffer); // links - this.dataStart = newBuffer; - this.dataEnd = newBuffer + newCapacity; + let newCapacity = length << alignof(); + let newData = REALLOC(changetype(oldData), newCapacity); // registers on move + if (newData !== changetype(oldData)) { + this.data = changetype(newData); // links + this.dataStart = newData; + this.dataEnd = newData + newCapacity; } } } @@ -114,23 +118,21 @@ export class Array extends ArrayBufferView { // } fill(value: T, start: i32 = 0, end: i32 = i32.MAX_VALUE): this { - var base = this.dataStart; + var dataStart = this.dataStart; var length = this.length_; - start = start < 0 ? max(length + start, 0) : min(start, length); end = end < 0 ? max(length + end, 0) : min(end, length); - if (sizeof() == 1) { if (start < end) { memory.fill( - base + start, + dataStart + start, value, (end - start) ); } } else { for (; start < end; ++start) { - store(base + (start << alignof()), value); + store(dataStart + (start << alignof()), value); } } return this; @@ -144,9 +146,9 @@ export class Array extends ArrayBufferView { var length = this.length_; if (length == 0 || fromIndex >= length) return -1; if (fromIndex < 0) fromIndex = max(length + fromIndex, 0); - var base = this.dataStart; + var dataStart = this.dataStart; while (fromIndex < length) { - if (load(base + (fromIndex << alignof())) == searchElement) return fromIndex; + if (load(dataStart + (fromIndex << alignof())) == searchElement) return fromIndex; ++fromIndex; } return -1; @@ -155,11 +157,11 @@ export class Array extends ArrayBufferView { lastIndexOf(searchElement: T, fromIndex: i32 = this.length_): i32 { var length = this.length_; if (length == 0) return -1; - if (fromIndex < 0) fromIndex = length + fromIndex; // no need to clamp + if (fromIndex < 0) fromIndex = length + fromIndex; else if (fromIndex >= length) fromIndex = length - 1; - var base = this.dataStart; - while (fromIndex >= 0) { // ^ - if (load(base + (fromIndex << alignof())) == searchElement) return fromIndex; + var dataStart = this.dataStart; + while (fromIndex >= 0) { + if (load(dataStart + (fromIndex << alignof())) == searchElement) return fromIndex; --fromIndex; } return -1; @@ -177,19 +179,32 @@ export class Array extends ArrayBufferView { concat(other: Array): Array { var thisLen = this.length_; var otherLen = select(0, other.length_, other === null); - var outLen = thisLen + otherLen; - var out = new Array(outLen); - if (thisLen) { - memory.copy(out.dataStart, this.dataStart, thisLen << alignof()); - } - if (otherLen) { - memory.copy(out.dataStart + (thisLen << alignof()), other.dataStart, otherLen << alignof()); + var out = new Array(thisLen + otherLen); + var outStart = out.dataStart; + var thisSize = thisLen << alignof(); + if (isManaged()) { + let thisStart = this.dataStart; + for (let offset: usize = 0; offset < thisSize; offset += sizeof()) { + let element = load(thisStart + offset); + store(outStart + offset, element); + LINK(changetype(element), changetype(out)); + } + let otherStart = other.dataStart; + let otherSize = otherLen << alignof(); + for (let offset: usize = 0; offset < otherSize; offset += sizeof()) { + let element = load(otherStart + offset); + store(outStart + thisSize + offset, element); + LINK(changetype(element), changetype(out)); + } + } else { + memory.copy(outStart, this.dataStart, thisSize); + memory.copy(outStart + thisSize, other.dataStart, otherLen << alignof()); } return out; } copyWithin(target: i32, start: i32, end: i32 = i32.MAX_VALUE): this { - var buffer = this.buffer_; + var dataStart = this.dataStart; var len = this.length_; end = min(end, len); @@ -202,13 +217,13 @@ export class Array extends ArrayBufferView { from += count - 1; to += count - 1; while (count) { - STORE(buffer, to, LOAD(buffer, from)); + store(dataStart + (to << alignof()), load(dataStart + (from << alignof()))); --from, --to, --count; } } else { memory.copy( - changetype(buffer) + HEADER_SIZE + (to << alignof()), - changetype(buffer) + HEADER_SIZE + (from << alignof()), + dataStart + (to << alignof()), + dataStart + (from << alignof()), count << alignof() ); } @@ -231,14 +246,15 @@ export class Array extends ArrayBufferView { map(callbackfn: (value: T, index: i32, array: Array) => U): Array { var length = this.length_; - var result = new Array(length); - var resultStart = result.dataStart; + var out = new Array(length); + var outStart = out.dataStart; for (let index = 0; index < min(length, this.length_); ++index) { - let element = load(this.dataStart + (index << alignof())); - store(resultStart + (index << alignof()), element); - if (isManaged()) LINK(changetype(element), changetype(result)); + let value = load(this.dataStart + (index << alignof())); + let result = callbackfn(value, index, this); + store(outStart + (index << alignof()), result); + if (isManaged()) LINK(changetype(result), changetype(out)); } - return result; + return out; } filter(callbackfn: (value: T, index: i32, array: Array) => bool): Array { @@ -360,9 +376,10 @@ export class Array extends ArrayBufferView { reverse(): Array { var base = this.dataStart; for (let front = 0, back = this.length_ - 1; front < back; ++front, --back) { - let temp: T = load(base, front); - store(base + (front << alignof()), load(base + (back << alignof()))); - store(base + (back << alignof()), temp); + let temp = load(base, front); + let dest = base + (back << alignof()); + store(base + (front << alignof()), load(dest)); + store(dest, temp); } return this; } diff --git a/std/assembly/runtime.ts b/std/assembly/runtime.ts index 085851e2..b0edc9d7 100644 --- a/std/assembly/runtime.ts +++ b/std/assembly/runtime.ts @@ -1,7 +1,4 @@ -import { - AL_MASK, - MAX_SIZE_32 -} from "./internal/allocator"; +import { AL_MASK, MAX_SIZE_32 } from "./util/allocator"; @builtin export declare const HEAP_BASE: usize; @@ -151,9 +148,9 @@ export abstract class ArrayBufferBase { export abstract class ArrayBufferView { [key: number]: number; - protected data: ArrayBuffer; - protected dataStart: usize; - protected dataEnd: usize; + @unsafe data: ArrayBuffer; + @unsafe dataStart: usize; + @unsafe dataEnd: usize; constructor(length: i32, alignLog2: i32) { if (length > ArrayBufferBase.MAX_BYTELENGTH >>> alignLog2) throw new RangeError("Invalid length"); @@ -161,11 +158,7 @@ export abstract class ArrayBufferView { var buffer = new ArrayBuffer(byteLength); this.data = buffer; this.dataStart = changetype(buffer); - this.dataEnd = changetype(buffer) + length; - } - - get buffer(): ArrayBuffer { - return this.data; + this.dataEnd = changetype(buffer) + length; } get byteOffset(): i32 { @@ -175,6 +168,11 @@ export abstract class ArrayBufferView { get byteLength(): i32 { return (this.dataEnd - this.dataStart); } + + get length(): i32 { + ERROR("not implemented"); + return unreachable(); + } } export abstract class StringBase { @@ -185,7 +183,7 @@ export abstract class StringBase { } } -import { memcmp, memmove, memset } from "./internal/memory"; +import { memcmp, memmove, memset } from "./util/memory"; export namespace memory { @builtin export declare function size(): i32; diff --git a/std/assembly/string.ts b/std/assembly/string.ts index bc4a2e28..4c89dbd6 100644 --- a/std/assembly/string.ts +++ b/std/assembly/string.ts @@ -9,7 +9,7 @@ import { parse, CharCode, isWhiteSpaceOrLineTerminator -} from "./internal/string"; +} from "./util/string"; @sealed export class String extends StringBase { @@ -431,8 +431,8 @@ import { return len; } - static fromUTF8(ptr: usize, len: usize): String { - if (len < 1) return changetype(""); + static fromUTF8(ptr: usize, len: usize): string { + if (len < 1) return changetype(""); var ptrPos = 0; var buf = memory.allocate(len << 1); var bufPos = 0; @@ -468,10 +468,10 @@ import { } } assert(ptrPos == len); - var out = ALLOC((bufPos >> 1)); + var out = ALLOC(bufPos); memory.copy(changetype(out), buf, bufPos); memory.free(buf); - return REGISTER(out); + return REGISTER(out); } toUTF8(): usize { diff --git a/std/assembly/typedarray.ts b/std/assembly/typedarray.ts index 0bacb1c7..488bbe80 100644 --- a/std/assembly/typedarray.ts +++ b/std/assembly/typedarray.ts @@ -1,14 +1,5 @@ -import { - ALLOC, - REGISTER, - LINK, - ArrayBufferView -} from "./runtime"; - -import { - COMPARATOR, - SORT as SORT_IMPL -} from "./internal/sort"; +import { ALLOC, REGISTER, LINK, ArrayBufferView } from "./runtime"; +import { COMPARATOR, SORT as SORT_IMPL } from "./util/sort"; function clampToByte(value: i32): i32 { return ~(value >> 31) & (((255 - value) >> 31) | value); // & 255 @@ -18,10 +9,16 @@ export class Int8Array extends ArrayBufferView { @lazy static readonly BYTES_PER_ELEMENT: usize = sizeof(); constructor(length: i32) { - super(length, 0); + super(length, alignof()); } - get length(): i32 { return this.byteLength; } + get buffer(): ArrayBuffer { + return this.data; + } + + get length(): i32 { + return this.byteLength; + } fill(value: i32, start: i32 = 0, end: i32 = i32.MAX_VALUE): Int8Array { return FILL(this, value, start, end); @@ -74,7 +71,7 @@ export class Uint8Array extends ArrayBufferView { @lazy static readonly BYTES_PER_ELEMENT: usize = sizeof(); constructor(length: i32) { - super(length, 0); + super(length, alignof()); } get length(): i32 { return this.byteLength; } @@ -180,10 +177,16 @@ export class Int16Array extends ArrayBufferView { @lazy static readonly BYTES_PER_ELEMENT: usize = sizeof(); constructor(length: i32) { - super(length, 1); + super(length, alignof()); } - get length(): i32 { return this.byteLength >>> 1; } + get buffer(): ArrayBuffer { + return this.data; + } + + get length(): i32 { + return this.byteLength >>> 1; + } fill(value: i32, start: i32 = 0, end: i32 = i32.MAX_VALUE): Int16Array { return FILL(this, value, start, end); @@ -236,10 +239,16 @@ export class Uint16Array extends ArrayBufferView { @lazy static readonly BYTES_PER_ELEMENT: usize = sizeof(); constructor(length: i32) { - super(length, 1); + super(length, alignof()); } - get length(): i32 { return this.byteLength >>> 1; } + get buffer(): ArrayBuffer { + return this.data; + } + + get length(): i32 { + return this.byteLength >>> 1; + } fill(value: u32, start: i32 = 0, end: i32 = i32.MAX_VALUE): Uint16Array { return FILL(this, value, start, end); @@ -292,10 +301,16 @@ export class Int32Array extends ArrayBufferView { @lazy static readonly BYTES_PER_ELEMENT: usize = sizeof(); constructor(length: i32) { - super(length, 2); + super(length, alignof()); } - get length(): i32 { return this.byteLength >>> 2; } + get buffer(): ArrayBuffer { + return this.data; + } + + get length(): i32 { + return this.byteLength >>> 2; + } fill(value: i32, start: i32 = 0, end: i32 = i32.MAX_VALUE): Int32Array { return FILL(this, value, start, end); @@ -348,10 +363,16 @@ export class Uint32Array extends ArrayBufferView { @lazy static readonly BYTES_PER_ELEMENT: usize = sizeof(); constructor(length: i32) { - super(length, 2); + super(length, alignof()); } - get length(): i32 { return this.byteLength >>> 2; } + get buffer(): ArrayBuffer { + return this.data; + } + + get length(): i32 { + return this.byteLength >>> 2; + } fill(value: u32, start: i32 = 0, end: i32 = i32.MAX_VALUE): Uint32Array { return FILL(this, value, start, end); @@ -404,10 +425,16 @@ export class Int64Array extends ArrayBufferView { @lazy static readonly BYTES_PER_ELEMENT: usize = sizeof(); constructor(length: i32) { - super(length, 3); + super(length, alignof()); } - get length(): i32 { return this.byteLength >>> 3; } + get buffer(): ArrayBuffer { + return this.data; + } + + get length(): i32 { + return this.byteLength >>> 3; + } fill(value: i64, start: i32 = 0, end: i32 = i32.MAX_VALUE): Int64Array { return FILL(this, value, start, end); @@ -460,10 +487,16 @@ export class Uint64Array extends ArrayBufferView { @lazy static readonly BYTES_PER_ELEMENT: usize = sizeof(); constructor(length: i32) { - super(length, 3); + super(length, alignof()); } - get length(): i32 { return this.byteLength >>> 3; } + get buffer(): ArrayBuffer { + return this.data; + } + + get length(): i32 { + return this.byteLength >>> 3; + } fill(value: u64, start: i32 = 0, end: i32 = i32.MAX_VALUE): Uint64Array { return FILL(this, value, start, end); @@ -516,10 +549,16 @@ export class Float32Array extends ArrayBufferView { @lazy static readonly BYTES_PER_ELEMENT: usize = sizeof(); constructor(length: i32) { - super(length, 2); + super(length, alignof()); } - get length(): i32 { return this.byteLength >>> 2; } + get buffer(): ArrayBuffer { + return this.data; + } + + get length(): i32 { + return this.byteLength >>> 2; + } fill(value: f32, start: i32 = 0, end: i32 = i32.MAX_VALUE): Float32Array { return FILL(this, value, start, end); @@ -572,10 +611,16 @@ export class Float64Array extends ArrayBufferView { @lazy static readonly BYTES_PER_ELEMENT: usize = sizeof(); constructor(length: i32) { - super(length, 3); + super(length, alignof()); } - get length(): i32 { return this.byteLength >>> 3; } + get buffer(): ArrayBuffer { + return this.data; + } + + get length(): i32 { + return this.byteLength >>> 3; + } fill(value: f64, start: i32 = 0, end: i32 = i32.MAX_VALUE): Float64Array { return FILL(this, value, start, end); diff --git a/std/assembly/vector.ts b/std/assembly/vector.ts index 0b264a39..e39e402f 100644 --- a/std/assembly/vector.ts +++ b/std/assembly/vector.ts @@ -1,3 +1,2 @@ -@sealed -export abstract class V128 { +@sealed export class V128 { }