From 8e9586783fe7aca0b3fef680e06bd11655f41256 Mon Sep 17 00:00:00 2001 From: dcode Date: Tue, 12 Mar 2019 02:14:30 +0100 Subject: [PATCH] I'm lost --- std/assembly/arraybuffer.ts | 49 ++++++++++++----------- std/assembly/internal/typedarray.ts | 8 ++-- std/assembly/runtime.ts | 61 ++++++++++++++++++----------- 3 files changed, 69 insertions(+), 49 deletions(-) diff --git a/std/assembly/arraybuffer.ts b/std/assembly/arraybuffer.ts index d1cef3e1..1d274aa9 100644 --- a/std/assembly/arraybuffer.ts +++ b/std/assembly/arraybuffer.ts @@ -5,45 +5,48 @@ import { } from "./runtime"; import { - Uint8ClampedArray, - Uint8Array, Int8Array, - Uint16Array, + Uint8Array, + Uint8ClampedArray, Int16Array, - Uint32Array, + Uint16Array, Int32Array, + Uint32Array, + Int64Array, Uint64Array, - Int64Array + Float32Array, + Float64Array } from "./typedarray"; import { DataView } from "./dataview"; -@sealed -export class ArrayBuffer extends ArrayBufferBase { +@sealed export class ArrayBuffer extends ArrayBufferBase { @inline static isView(value: T): bool { - if (value === null) return false; - if (value instanceof Uint8ClampedArray) return true; - if (value instanceof Uint8Array) return true; - if (value instanceof Int8Array) return true; - if (value instanceof Uint16Array) return true; - if (value instanceof Int16Array) return true; - if (value instanceof Uint32Array) return true; - if (value instanceof Int32Array) return true; - if (value instanceof Uint64Array) return true; - if (value instanceof Int64Array) return true; - if (value instanceof DataView) return true; + if (value) { + if (value instanceof Int8Array) return true; + if (value instanceof Uint8Array) return true; + if (value instanceof Uint8ClampedArray) return true; + if (value instanceof Int16Array) return true; + if (value instanceof Uint16Array) return true; + if (value instanceof Int32Array) return true; + if (value instanceof Uint32Array) return true; + if (value instanceof Int64Array) return true; + if (value instanceof Uint64Array) return true; + if (value instanceof Float32Array) return true; + if (value instanceof Float64Array) return true; + if (value instanceof DataView) return true; + } return false; } slice(begin: i32 = 0, end: i32 = ArrayBuffer.MAX_BYTELENGTH): ArrayBuffer { - var len = this.byteLength; - begin = begin < 0 ? max(len + begin, 0) : min(begin, len); - end = end < 0 ? max(len + end, 0) : min(end, len); - len = max(end - begin, 0); - var outSize = len; + var length = this.byteLength; + begin = begin < 0 ? max(length + begin, 0) : min(begin, length); + end = end < 0 ? max(length + end , 0) : min(end , length); + var outSize = max(end - begin, 0); var out = ALLOC_RAW(outSize); memory.copy(out, changetype(this) + begin, outSize); return REGISTER(out); diff --git a/std/assembly/internal/typedarray.ts b/std/assembly/internal/typedarray.ts index db9f7d3f..2364f325 100644 --- a/std/assembly/internal/typedarray.ts +++ b/std/assembly/internal/typedarray.ts @@ -1,5 +1,5 @@ import { - ALLOC, + ALLOC_RAW, REGISTER, LINK } from "../runtime"; @@ -109,11 +109,13 @@ export abstract class TypedArray { else begin = min(begin, length); if (end < 0) end = max(length + end, begin); else end = max(min(end, length), begin); - var out = ALLOC(offsetof()); + var out = ALLOC_RAW(offsetof()); store(out, buffer, offsetof("buffer")); + store(out, buffer + (begin << alignof()), offsetof("dataStart")); + store(out, buffer + (end << alignof()), offsetof("dataStart")); store(out, array.byteOffset + (begin << alignof()), offsetof("byteOffset")); store(out, (end - begin) << alignof(), offsetof("byteLength")); - LINK(buffer, REGISTER(out)); // register first, then link + LINK(buffer, REGISTER(out)); // register first, then link return changetype(out); } diff --git a/std/assembly/runtime.ts b/std/assembly/runtime.ts index 746d7bc4..085851e2 100644 --- a/std/assembly/runtime.ts +++ b/std/assembly/runtime.ts @@ -113,17 +113,18 @@ function unref(ref: usize): HEADER { } /** Frees an object. Must not have been registered with GC yet. */ -@unsafe export function FREE(ref: usize): void { - memory.free(changetype(unref(ref))); +@unsafe @inline export function FREE(ref: T): void { + memory.free(changetype(unref(changetype(ref)))); } /** Registers a managed object. Cannot be free'd anymore afterwards. */ -@unsafe @inline export function REGISTER(ref: usize): TRet { +@unsafe @inline export function REGISTER(ref: usize): T { + if (!isReference()) ERROR("reference expected"); // see comment in REALLOC why this is useful. also inline this because // it's generic so we don't get a bunch of functions. unref(ref).classId = gc.classId(); if (GC) gc.register(ref); - return changetype(ref); + return changetype(ref); } /** Links a managed object with its managed parent. */ @@ -134,51 +135,51 @@ function unref(ref: usize): HEADER { if (GC) gc.link(changetype(ref), changetype(parentRef)); // tslint:disable-line } -/** ArrayBuffer base class. */ export abstract class ArrayBufferBase { @lazy static readonly MAX_BYTELENGTH: i32 = MAX_SIZE_32 - HEADER_SIZE; - get byteLength(): i32 { - return changetype
(changetype(this) - HEADER_SIZE).payloadSize; - } + constructor(length: i32) { if (length > ArrayBufferBase.MAX_BYTELENGTH) throw new RangeError("Invalid array buffer length"); return REGISTER(ALLOC(length)); } + + get byteLength(): i32 { + return changetype
(changetype(this) - HEADER_SIZE).payloadSize; + } } -/** Typed array base class. */ export abstract class ArrayBufferView { [key: number]: number; - @unsafe buffer: ArrayBuffer; - @unsafe dataStart: usize; - @unsafe dataEnd: usize; + protected data: ArrayBuffer; + protected dataStart: usize; + protected dataEnd: usize; constructor(length: i32, alignLog2: i32) { if (length > ArrayBufferBase.MAX_BYTELENGTH >>> alignLog2) throw new RangeError("Invalid length"); var byteLength = length << alignLog2; var buffer = new ArrayBuffer(byteLength); - this.buffer = buffer; + this.data = buffer; this.dataStart = changetype(buffer); this.dataEnd = changetype(buffer) + length; } + get buffer(): ArrayBuffer { + return this.data; + } + get byteOffset(): i32 { - return this.dataStart - changetype(this.buffer); + return (this.dataStart - changetype(this.data)); } get byteLength(): i32 { - return this.dataEnd - this.dataStart; - } - - get length(): i32 { - return unreachable(); + return (this.dataEnd - this.dataStart); } } -/** String base class. */ export abstract class StringBase { @lazy static readonly MAX_LENGTH: i32 = (MAX_SIZE_32 - HEADER_SIZE) >> 1; + get length(): i32 { return changetype
(changetype(this) - HEADER_SIZE).payloadSize >> 1; } @@ -186,35 +187,44 @@ export abstract class StringBase { import { memcmp, memmove, memset } from "./internal/memory"; -/** Memory manager interface. */ export namespace memory { @builtin export declare function size(): i32; + @builtin @unsafe export declare function grow(pages: i32): i32; + @builtin @unsafe @inline export function fill(dst: usize, c: u8, n: usize): void { memset(dst, c, n); // fallback if "bulk-memory" isn't enabled } + @builtin @unsafe @inline export function copy(dst: usize, src: usize, n: usize): void { memmove(dst, src, n); // fallback if "bulk-memory" isn't enabled } + @unsafe export function init(segmentIndex: u32, srcOffset: usize, dstOffset: usize, n: usize): void { ERROR("not implemented"); } + @unsafe export function drop(segmentIndex: u32): void { ERROR("not implemented"); } + @stub @inline export function allocate(size: usize): usize { ERROR("stub: missing memory manager"); return unreachable(); } + @stub @unsafe @inline export function free(ptr: usize): void { ERROR("stub: missing memory manager"); } + @stub @unsafe @inline export function reset(): void { ERROR("stub: not supported by memory manager"); } + @inline export function compare(vl: usize, vr: usize, n: usize): i32 { return memcmp(vl, vr, n); } + @unsafe export function repeat(dst: usize, src: usize, srcLength: usize, count: usize): void { var index: usize = 0; var total = srcLength * count; @@ -225,15 +235,20 @@ export namespace memory { } } -/** Garbage collector interface. */ export namespace gc { @builtin @unsafe export declare function classId(): u32; + @builtin @unsafe export declare function iterateRoots(fn: (ref: usize) => void): void; + @stub @unsafe export function register(ref: usize): void { ERROR("stub: missing garbage collector"); } + @stub @unsafe export function link(ref: usize, parentRef: usize): void { ERROR("stub: missing garbage collector"); } - @stub export function collect(): void {} + + @stub export function collect(): void { + WARNING("stub: missing garbage collector"); + } }