From 5a2ab3d7ecc7ecb49c62892bad0b4bf5ebede038 Mon Sep 17 00:00:00 2001 From: dcode Date: Sun, 10 Mar 2019 02:57:05 +0100 Subject: [PATCH] what std/string would look like --- std/assembly/runtime/index.ts | 48 ++- std/assembly/runtime/itcm.ts | 8 + std/assembly/string.ts | 431 ++++++++++++----------- tests/compiler/std/runtime.optimized.wat | 42 +-- tests/compiler/std/runtime.ts | 7 +- tests/compiler/std/runtime.untouched.wat | 51 +-- 6 files changed, 302 insertions(+), 285 deletions(-) create mode 100644 std/assembly/runtime/itcm.ts diff --git a/std/assembly/runtime/index.ts b/std/assembly/runtime/index.ts index 497c0891..57ce7441 100644 --- a/std/assembly/runtime/index.ts +++ b/std/assembly/runtime/index.ts @@ -1,4 +1,4 @@ -import { AL_MASK } from "../internal/allocator"; +import { AL_MASK, MAX_SIZE_32 } from "../internal/allocator"; import { __rt_classid } from "../builtins"; /** Common runtime header of all objects. */ @@ -8,18 +8,22 @@ import { __rt_classid } from "../builtins"; /** Size of the allocated payload. */ payloadSize: u32; /** Reserved field for use by GC. Only present if GC is. */ - reserved1: usize; // itcm: tagged next + gc1: usize; // itcm: tagged next /** Reserved field for use by GC. Only present if GC is. */ - reserved2: usize; // itcm: prev + gc2: usize; // itcm: prev } +// Note that header data and layout isn't quite optimal depending on which allocator one +// decides to use, but it's done this way for maximum flexibility. Also remember that the +// runtime will most likely change significantly once reftypes and WASM GC are a thing. + /** Whether a GC is present or not. */ -@inline export const GC = isDefined(__REGISTER_IMPL); +@inline export const GC = isDefined(gc); /** Size of the common runtime header. */ @inline export const HEADER_SIZE: usize = GC - ? (offsetof
( ) + AL_MASK) & ~AL_MASK // full header if GC is present - : (offsetof
("reserved1") + AL_MASK) & ~AL_MASK; // half header if GC is absent + ? (offsetof
( ) + AL_MASK) & ~AL_MASK // full header if GC is present + : (offsetof
("gc1") + AL_MASK) & ~AL_MASK; // half header if GC is absent /** Magic value used to validate common runtime headers. */ @inline export const HEADER_MAGIC: u32 = 0xA55E4B17; @@ -41,8 +45,8 @@ export function ALLOC(payloadSize: u32): usize { header.classId = HEADER_MAGIC; header.payloadSize = payloadSize; if (GC) { - header.reserved1 = 0; - header.reserved2 = 0; + header.gc1 = 0; + header.gc2 = 0; } var ref = changetype(header) + HEADER_SIZE; memory.fill(ref, 0, payloadSize); @@ -60,8 +64,8 @@ export function REALLOC(ref: usize, newPayloadSize: u32): usize { let newHeader = changetype
(memory.allocate(newAlignedSize)); newHeader.classId = HEADER_MAGIC; if (GC) { - newHeader.reserved1 = 0; - newHeader.reserved2 = 0; + newHeader.gc1 = 0; + newHeader.gc2 = 0; } let newRef = changetype(newHeader) + HEADER_SIZE; memory.copy(newRef, ref, payloadSize); @@ -85,7 +89,7 @@ export function REALLOC(ref: usize, newPayloadSize: u32): usize { return ref; } -function ensureUnregistered(ref: usize): HEADER { +function unref(ref: usize): HEADER { assert(ref >= HEAP_BASE + HEADER_SIZE); // must be a heap object var header = changetype
(ref - HEADER_SIZE); assert(header.classId == HEADER_MAGIC); // must be unregistered @@ -94,17 +98,28 @@ function ensureUnregistered(ref: usize): HEADER { /** Frees an object. Must not have been registered with GC yet. */ export function FREE(ref: usize): void { - memory.free(changetype(ensureUnregistered(ref))); + memory.free(changetype(unref(ref))); } -/** Registers a managed object with GC. Cannot be free'd anymore afterwards. */ -@inline export function REGISTER(ref: usize, parentRef: usize): void { - ensureUnregistered(ref).classId = __rt_classid(); - if (GC) __REGISTER_IMPL(ref, parentRef); // tslint:disable-line +/** Registers a managed object. Cannot be free'd anymore afterwards. */ +@inline export function REGISTER(ref: usize): T { + // inline this because it's generic so we don't get a bunch of functions + unref(ref).classId = __rt_classid(); + if (GC) gc.register(ref); + return changetype(ref); +} + +/** Links a managed object with its managed parent. */ +export function LINK(ref: usize, parentRef: usize): void { + assert(ref >= HEAP_BASE + HEADER_SIZE); // must be a heap object + var header = changetype
(ref - HEADER_SIZE); + assert(header.classId != HEADER_MAGIC && header.gc1 != 0 && header.gc2 != 0); // must be registered + if (GC) gc.link(ref, parentRef); // tslint:disable-line } /** ArrayBuffer base class. */ export abstract class ArrayBufferBase { + static readonly MAX_BYTELENGTH: i32 = MAX_SIZE_32 - HEADER_SIZE; get byteLength(): i32 { return changetype
(changetype(this) - HEADER_SIZE).payloadSize; } @@ -112,6 +127,7 @@ export abstract class ArrayBufferBase { /** String base class. */ export abstract class StringBase { + static readonly MAX_LENGTH: i32 = (MAX_SIZE_32 - HEADER_SIZE) >> 1; get length(): i32 { return changetype
(changetype(this) - HEADER_SIZE).payloadSize >> 1; } diff --git a/std/assembly/runtime/itcm.ts b/std/assembly/runtime/itcm.ts new file mode 100644 index 00000000..19da440b --- /dev/null +++ b/std/assembly/runtime/itcm.ts @@ -0,0 +1,8 @@ +@global namespace gc { + @unsafe export function register(ref: usize): void { + } + @unsafe export function link(ref: usize, parentRef: usize): void { + } + export function collect(): void { + } +} diff --git a/std/assembly/string.ts b/std/assembly/string.ts index b6ca9f73..816bab4f 100644 --- a/std/assembly/string.ts +++ b/std/assembly/string.ts @@ -1,11 +1,10 @@ import { - HEADER_SIZE, - MAX_LENGTH, - allocateUnsafe, - compareUnsafe, - repeatUnsafe, - copyUnsafe, - isWhiteSpaceOrLineTerminator, + ALLOC, + REGISTER, + StringBase +} from "./runtime"; + +import { CharCode, parse } from "./internal/string"; @@ -14,94 +13,141 @@ import { STORE } from "./internal/arraybuffer"; -@sealed -export class String { +function compareImpl(str1: String, offset1: usize, str2: String, offset2: usize, len: usize): i32 { + var result: i32 = 0; + var ptr1 = changetype(str1) + (offset1 << 1); + var ptr2 = changetype(str2) + (offset2 << 1); + while (len && !(result = load(ptr1) - load(ptr2))) { + --len, ptr1 += 2, ptr2 += 2; + } + return result; +} - readonly length: i32; // capped to [0, MAX_LENGTH] +function repeatImpl(dst: usize, dstIndex: usize, src: String, count: i32): void { + var length = src.length; + if (ASC_SHRINK_LEVEL > 1) { + let strLen = length << 1; + let to = changetype(dst) + (dstIndex << 1); + let from = changetype(src); + for (let i = 0, len = strLen * count; i < len; i += strLen) { + memory.copy(to + i, from, strLen); + } + } else { + switch (length) { + case 0: break; + case 1: { + let cc = load(changetype(src)); + let out = changetype(dst) + (dstIndex << 1); + for (let i = 0; i < count; ++i) { + store(out + (i << 1), cc); + } + break; + } + case 2: { + let cc = load(changetype(src)); + let out = changetype(dst) + (dstIndex << 1); + for (let i = 0; i < count; ++i) { + store(out + (i << 2), cc); + } + break; + } + case 3: { + let cc1 = load(changetype(src)); + let cc2 = load(changetype(src), 4); + let out = changetype(dst) + (dstIndex << 1); + for (let i = 0; i < count; ++i) { + store(out + (i << 2), cc1); + store(out + (i << 1), cc2, 4); + } + break; + } + case 4: { + let cc = load(changetype(src)); + let out = changetype(dst) + (dstIndex << 1); + for (let i = 0; i < count; ++i) { + store(out + (i << 3), cc); + } + break; + } + default: { + let strLen = length << 1; + let to = changetype(dst) + (dstIndex << 1); + let from = changetype(src); + for (let i = 0, len = strLen * count; i < len; i += strLen) { + memory.copy(to + i, from, strLen); + } + break; + } + } + } +} + +function isWhiteSpaceOrLineTerminator(c: u16): bool { + switch (c) { + case 9: // + case 10: // + case 13: // + case 11: // + case 12: // + case 32: // + case 160: // + case 8232: // + case 8233: // + case 65279: return true; // + default: return false; + } +} + +@sealed +export class String extends StringBase { // TODO Add and handle second argument static fromCharCode(code: i32): String { - var out = allocateUnsafe(1); - store( - changetype(out), - code, - HEADER_SIZE - ); - return out; + var out = ALLOC(2); + store(out, code); + return REGISTER(out); } static fromCodePoint(code: i32): String { assert(code <= 0x10FFFF); var sur = code > 0xFFFF; - var out = allocateUnsafe(sur + 1); + var out = ALLOC((sur + 1) << 1); if (!sur) { - store( - changetype(out), - code, - HEADER_SIZE - ); + store(out, code); } else { code -= 0x10000; let hi: u32 = (code >>> 10) + 0xD800; let lo: u32 = (code & 0x3FF) + 0xDC00; - store( - changetype(out), - (hi << 16) | lo, - HEADER_SIZE - ); + store(out, (hi << 16) | lo); } - return out; + return REGISTER(out); } - @operator("[]") - charAt(pos: i32): String { + @operator("[]") charAt(pos: i32): String { assert(this !== null); - if (pos >= this.length) return changetype(""); - - var out = allocateUnsafe(1); - store( - changetype(out), - load( - changetype(this) + (pos << 1), - HEADER_SIZE - ), - HEADER_SIZE - ); - return out; + var out = ALLOC(2); + store(out, load(changetype(this) + (pos << 1))); + return REGISTER(out); } charCodeAt(pos: i32): i32 { assert(this !== null); if (pos >= this.length) return -1; // (NaN) - - return load( - changetype(this) + (pos << 1), - HEADER_SIZE - ); + return load(changetype(this) + (pos << 1)); } codePointAt(pos: i32): i32 { assert(this !== null); if (pos >= this.length) return -1; // (undefined) - - var first = load( - changetype(this) + (pos << 1), - HEADER_SIZE - ); - if (first < 0xD800 || first > 0xDBFF || pos + 1 == this.length) { - return first; - } - var second = load( - changetype(this) + ((pos + 1) << 1), - HEADER_SIZE - ); + var first = load(changetype(this) + (pos << 1)); + if (first < 0xD800 || first > 0xDBFF || pos + 1 == this.length) return first; + var second = load(changetype(this) + ((pos + 1) << 1)); if (second < 0xDC00 || second > 0xDFFF) return first; return ((first - 0xD800) << 10) + (second - 0xDC00) + 0x10000; } - @operator("+") - private static __concat(left: String, right: String): String { + @operator("+") static concat(left: String, right: String): String { if (!changetype(left)) left = changetype("null"); return left.concat(right); } @@ -109,90 +155,71 @@ export class String { concat(other: String): String { assert(this !== null); if (other === null) other = changetype("null"); - - var thisLen: isize = this.length; - var otherLen: isize = other.length; - var outLen: usize = thisLen + otherLen; - if (outLen == 0) return changetype(""); - var out = allocateUnsafe(outLen); - copyUnsafe(out, 0, this, 0, thisLen); - copyUnsafe(out, thisLen, other, 0, otherLen); - return out; + var thisSize: isize = this.length << 1; + var otherSize: isize = other.length << 1; + var outSize: usize = thisSize + otherSize; + if (outSize == 0) return changetype(""); + var out = ALLOC(outSize); + memory.copy(out, changetype(this), thisSize); + memory.copy(out + thisSize, changetype(other), otherSize); + return REGISTER(out); } - endsWith(searchString: String, endPosition: i32 = MAX_LENGTH): bool { + endsWith(searchString: String, endPosition: i32 = String.MAX_LENGTH): bool { assert(this !== null); if (searchString === null) return false; var end = min(max(endPosition, 0), this.length); var searchLength: isize = searchString.length; var start: isize = end - searchLength; if (start < 0) return false; - return !compareUnsafe(this, start, searchString, 0, searchLength); + return !compareImpl(this, start, searchString, 0, searchLength); } - @operator("==") - private static __eq(left: String, right: String): bool { + @operator("==") static eq(left: String, right: String): bool { if (left === right) return true; if (left === null || right === null) return false; - var leftLength = left.length; if (leftLength != right.length) return false; - - return !compareUnsafe(left, 0, right, 0, leftLength); + return !compareImpl(left, 0, right, 0, leftLength); } - @operator("!=") - private static __ne(left: String, right: String): bool { - return !this.__eq(left, right); + @operator("!=") static ne(left: String, right: String): bool { + return !this.eq(left, right); } - @operator(">") - private static __gt(left: String, right: String): bool { + @operator(">") static gt(left: String, right: String): bool { if (left === right || left === null || right === null) return false; - var leftLength = left.length; var rightLength = right.length; - if (!leftLength) return false; if (!rightLength) return true; - - var length = min(leftLength, rightLength); - return compareUnsafe(left, 0, right, 0, length) > 0; + return compareImpl(left, 0, right, 0, min(leftLength, rightLength)) > 0; } - @operator(">=") - private static __gte(left: String, right: String): bool { - return !this.__lt(left, right); + @operator(">=") static gte(left: String, right: String): bool { + return !this.lt(left, right); } - @operator("<") - private static __lt(left: String, right: String): bool { + @operator("<") static lt(left: String, right: String): bool { if (left === right || left === null || right === null) return false; - var leftLength = left.length; var rightLength = right.length; - if (!rightLength) return false; if (!leftLength) return true; - - var length = min(leftLength, rightLength); - return compareUnsafe(left, 0, right, 0, length) < 0; + return compareImpl(left, 0, right, 0, min(leftLength, rightLength)) < 0; } - @operator("<=") - private static __lte(left: String, right: String): bool { - return !this.__gt(left, right); + @operator("<=") static lte(left: String, right: String): bool { + return !this.gt(left, right); } - @inline - includes(searchString: String, position: i32 = 0): bool { + @inline includes(searchString: String, position: i32 = 0): bool { return this.indexOf(searchString, position) != -1; } indexOf(searchString: String, fromIndex: i32 = 0): i32 { assert(this !== null); if (searchString === null) searchString = changetype("null"); - var searchLen: isize = searchString.length; if (!searchLen) return 0; var len: isize = this.length; @@ -200,7 +227,7 @@ export class String { var start = min(max(fromIndex, 0), len); len -= searchLen; for (let k: isize = start; k <= len; ++k) { - if (!compareUnsafe(this, k, searchString, 0, searchLen)) return k; + if (!compareImpl(this, k, searchString, 0, searchLen)) return k; } return -1; } @@ -208,14 +235,13 @@ export class String { lastIndexOf(searchString: String, fromIndex: i32 = i32.MAX_VALUE): i32 { assert(this !== null); if (searchString === null) searchString = changetype("null"); - var len: isize = this.length; var searchLen: isize = searchString.length; if (!searchLen) return len; if (!len) return -1; var start = min(max(fromIndex, 0), len - searchLen); for (let k = start; k >= 0; --k) { - if (!compareUnsafe(this, k, searchString, 0, searchLen)) return k; + if (!compareImpl(this, k, searchString, 0, searchLen)) return k; } return -1; } @@ -223,13 +249,12 @@ export class String { startsWith(searchString: String, position: i32 = 0): bool { assert(this !== null); if (searchString === null) searchString = changetype("null"); - var pos: isize = position; var len: isize = this.length; var start = min(max(pos, 0), len); var searchLength: isize = searchString.length; if (searchLength + start > len) return false; - return !compareUnsafe(this, start, searchString, 0, searchLength); + return !compareImpl(this, start, searchString, 0, searchLength); } substr(start: i32, length: i32 = i32.MAX_VALUE): String { @@ -240,52 +265,52 @@ export class String { if (intStart < 0) intStart = max(size + intStart, 0); var resultLength = min(max(end, 0), size - intStart); if (resultLength <= 0) return changetype(""); - var out = allocateUnsafe(resultLength); - copyUnsafe(out, 0, this, intStart, resultLength); - return out; + var out = ALLOC(resultLength << 1); + memory.copy(out, changetype(this) + intStart, resultLength); + return REGISTER(out); } substring(start: i32, end: i32 = i32.MAX_VALUE): String { assert(this !== null); - var len = this.length; - var finalStart = min(max(start, 0), len); - var finalEnd = min(max(end, 0), len); - var from = min(finalStart, finalEnd); - var to = max(finalStart, finalEnd); - len = to - from; + var len: isize = this.length; + var finalStart = min(max(start, 0), len); + var finalEnd = min(max(end, 0), len); + var fromPos = min(finalStart, finalEnd) << 1; + var toPos = max(finalStart, finalEnd) << 1; + len = toPos - fromPos; if (!len) return changetype(""); - if (!from && to == this.length) return this; - var out = allocateUnsafe(len); - copyUnsafe(out, 0, this, from, len); - return out; + if (!fromPos && toPos == this.length) return this; + var out = ALLOC(len); + memory.copy(out, changetype(this) + fromPos, len); + return REGISTER(out); } trim(): String { assert(this !== null); - var length: usize = this.length; - + var length = this.length; + var size: usize = length << 1; while ( - length && + size && isWhiteSpaceOrLineTerminator( - load(changetype(this) + (length << 1), HEADER_SIZE) + load(changetype(this) + size) ) ) { - --length; + size -= 2; } - var start: usize = 0; + var offset: usize = 0; while ( - start < length && + offset < size && isWhiteSpaceOrLineTerminator( - load(changetype(this) + (start << 1), HEADER_SIZE) + load(changetype(this) + offset) ) ) { - ++start, --length; + offset += 2; size -= 2; } - if (!length) return changetype(""); - if (!start && length == this.length) return this; - var out = allocateUnsafe(length); - copyUnsafe(out, 0, this, start, length); - return out; + if (!size) return changetype(""); + if (!start && size == length << 1) return this; + var out = ALLOC(size); + memory.copy(out, changetype(this) + offset, size); + return REGISTER(out); } @inline @@ -300,40 +325,41 @@ export class String { trimStart(): String { assert(this !== null); - var start: isize = 0; - var len: isize = this.length; + var size = this.length << 1; + var offset: usize = 0; while ( - start < len && + offset < size && isWhiteSpaceOrLineTerminator( - load(changetype(this) + (start << 1), HEADER_SIZE) + load(changetype(this) + offset) ) ) { - ++start; + offset += 2; } - if (!start) return this; - var outLen = len - start; - if (!outLen) return changetype(""); - var out = allocateUnsafe(outLen); - copyUnsafe(out, 0, this, start, outLen); - return out; + if (!offset) return this; + size -= offset; + if (!size) return changetype(""); + var out = ALLOC(size); + memory.copy(out, changetype(this) + offset, size); + return REGISTER(out); } trimEnd(): String { assert(this !== null); - var len: isize = this.length; + var originalSize = this.length << 1; + var size = originalSize; while ( - len > 0 && + size && isWhiteSpaceOrLineTerminator( - load(changetype(this) + (len << 1), HEADER_SIZE) + load(changetype(this) + size) ) ) { - --len; + size -= 2; } - if (len <= 0) return changetype(""); - if (len == this.length) return this; - var out = allocateUnsafe(len); - copyUnsafe(out, 0, this, 0, len); - return out; + if (!size) return changetype(""); + if (size == originalSize) return this; + var out = ALLOC(size); + memory.copy(out, changetype(this), size); + return REGISTER(out); } padStart(targetLength: i32, padString: String = changetype(" ")): String { @@ -342,18 +368,22 @@ export class String { var padLen = padString.length; if (targetLength < length || !padLen) return this; var len = targetLength - length; - var out = allocateUnsafe(targetLength); + var out = ALLOC(targetLength << 1); if (len > padLen) { let count = (len - 1) / padLen; let base = count * padLen; let rest = len - base; - repeatUnsafe(out, 0, padString, count); - if (rest) copyUnsafe(out, base, padString, 0, rest); + repeatImpl(out, 0, padString, count); + if (rest) { + memory.copy(out + (base << 1), changetype(padString), rest << 1); + } } else { - copyUnsafe(out, 0, padString, 0, len); + memory.copy(out, changetype(padString), len << 1); } - if (length) copyUnsafe(out, len, this, 0, length); - return out; + if (length) { + memory.copy(out + (len << 1), changetype(this), length << 1); + } + return REGISTER(out); } padEnd(targetLength: i32, padString: String = changetype(" ")): String { @@ -362,18 +392,22 @@ export class String { var padLen = padString.length; if (targetLength < length || !padLen) return this; var len = targetLength - length; - var out = allocateUnsafe(targetLength); - if (length) copyUnsafe(out, 0, this, 0, length); + var out = ALLOC(targetLength); + if (length) { + memory.copy(out, changetype(this), length << 1); + } if (len > padLen) { let count = (len - 1) / padLen; let base = count * padLen; let rest = len - base; - repeatUnsafe(out, length, padString, count); - if (rest) copyUnsafe(out, base + length, padString, 0, rest); + repeatImpl(out, length, padString, count); + if (rest) { + memory.copy(out + ((base + length) << 1), changetype(padString), rest << 1); + } } else { - copyUnsafe(out, length, padString, 0, len); + memory.copy(out + (length << 1), changetype(padString), len << 1); } - return out; + return REGISTER(out); } repeat(count: i32 = 0): String { @@ -387,10 +421,9 @@ export class String { if (count == 0 || !length) return changetype(""); if (count == 1) return this; - - var result = allocateUnsafe(length * count); - repeatUnsafe(result, 0, this, count); - return result; + var out = ALLOC(length * count); + repeatImpl(out, 0, this, count); + return REGISTER(out); } slice(beginIndex: i32, endIndex: i32 = i32.MAX_VALUE): String { @@ -399,12 +432,12 @@ export class String { var end = endIndex < 0 ? max(endIndex + len, 0) : min(endIndex, len); len = end - begin; if (len <= 0) return changetype(""); - var out = allocateUnsafe(len); - copyUnsafe(out, 0, this, begin, len); - return out; + var out = ALLOC(len); + memory.copy(out, changetype(this) + (begin << 1), len << 1); + return REGISTER(out); } - split(separator: String = null, limit: i32 = i32.MAX_VALUE): String[] { + split(separator: String | null = null, limit: i32 = i32.MAX_VALUE): String[] { assert(this !== null); if (!limit) return new Array(); if (separator === null) return [this]; @@ -418,16 +451,14 @@ export class String { let result = new Array(length); let buffer = result.buffer_; for (let i: isize = 0; i < length; ++i) { - let char = allocateUnsafe(1); + let char = ALLOC(2); store( changetype(char), load( - changetype(this) + (i << 1), - HEADER_SIZE - ), - HEADER_SIZE + changetype(this) + (i << 1) + ) ); - STORE(buffer, i, char); + STORE(buffer, i, char); // FIXME: use store once AB is done as well } return result; } else if (!length) { @@ -440,9 +471,9 @@ export class String { while ((end = this.indexOf(separator, start)) != -1) { let len = end - start; if (len > 0) { - let out = allocateUnsafe(len); - copyUnsafe(out, 0, this, start, len); - result.push(out); + let out = ALLOC(len << 1); + memory.copy(out, changetype(this) + (start << 1), len << 1); + result.push(REGISTER(out)); } else { result.push(changetype("")); } @@ -456,9 +487,9 @@ export class String { } var len = length - start; if (len > 0) { - let out = allocateUnsafe(len); - copyUnsafe(out, 0, this, start, len); - result.push(out); + let out = ALLOC(len << 1); + memory.copy(out, changetype(this) + (start << 1), len << 1); + result.push(REGISTER(out)); } else { result.push(changetype("")); } @@ -474,7 +505,7 @@ export class String { var pos: usize = 0; var end = this.length; while (pos < end) { - let c = load(changetype(this) + (pos << 1), HEADER_SIZE); + let c = load(changetype(this) + (pos << 1)); if (c < 128) { len += 1; ++pos; } else if (c < 2048) { @@ -482,7 +513,7 @@ export class String { } else { if ( (c & 0xFC00) == 0xD800 && pos + 1 < end && - (load(changetype(this) + ((pos + 1) << 1), HEADER_SIZE) & 0xFC00) == 0xDC00 + (load(changetype(this) + ((pos + 1) << 1)) & 0xFC00) == 0xDC00 ) { len += 4; pos += 2; } else { @@ -530,10 +561,10 @@ export class String { } } assert(ptrPos == len); - var str = allocateUnsafe((bufPos >> 1)); - memory.copy(changetype(str) + HEADER_SIZE, buf, bufPos); + var out = ALLOC((bufPos >> 1)); + memory.copy(changetype(out), buf, bufPos); memory.free(buf); - return str; + return REGISTER(out); } toUTF8(): usize { @@ -542,7 +573,7 @@ export class String { var end = this.length; var off: usize = 0; while (pos < end) { - let c1 = load(changetype(this) + (pos << 1), HEADER_SIZE); + let c1 = load(changetype(this) + (pos << 1)); if (c1 < 128) { store(buf + off, c1); ++off; ++pos; @@ -554,7 +585,7 @@ export class String { } else { let ptr = buf + off; if ((c1 & 0xFC00) == 0xD800 && pos + 1 < end) { - let c2 = load(changetype(this) + ((pos + 1) << 1), HEADER_SIZE); + let c2 = load(changetype(this) + ((pos + 1) << 1)); if ((c2 & 0xFC00) == 0xDC00) { c1 = 0x10000 + ((c1 & 0x03FF) << 10) + (c2 & 0x03FF); store(ptr, c1 >> 18 | 240); @@ -596,17 +627,17 @@ export function parseFloat(str: String): f64 { if (!len) return NaN; var ptr = changetype(str) /* + HEAD -> offset */; - var code = load(ptr, HEADER_SIZE); + var code = load(ptr); // determine sign var sign: f64; if (code == CharCode.MINUS) { if (!--len) return NaN; - code = load(ptr += 2, HEADER_SIZE); + code = load(ptr += 2); sign = -1; } else if (code == CharCode.PLUS) { if (!--len) return NaN; - code = load(ptr += 2, HEADER_SIZE); + code = load(ptr += 2); sign = 1; } else { sign = 1; @@ -615,12 +646,12 @@ export function parseFloat(str: String): f64 { // calculate value var num: f64 = 0; while (len--) { - code = load(ptr, HEADER_SIZE); + code = load(ptr); if (code == CharCode.DOT) { ptr += 2; let fac: f64 = 0.1; // precision :( while (len--) { - code = load(ptr, HEADER_SIZE); + code = load(ptr); if (code == CharCode.E || code == CharCode.e) { assert(false); // TODO } diff --git a/tests/compiler/std/runtime.optimized.wat b/tests/compiler/std/runtime.optimized.wat index 4444ad55..aa243d22 100644 --- a/tests/compiler/std/runtime.optimized.wat +++ b/tests/compiler/std/runtime.optimized.wat @@ -21,7 +21,6 @@ (elem (i32.const 0) $null) (global $~lib/allocator/tlsf/ROOT (mut i32) (i32.const 0)) (global $std/runtime/register_ref (mut i32) (i32.const 0)) - (global $std/runtime/register_parentRef (mut i32) (i32.const 0)) (global $std/runtime/barrier1 (mut i32) (i32.const 0)) (global $std/runtime/barrier2 (mut i32) (i32.const 0)) (global $std/runtime/barrier3 (mut i32) (i32.const 0)) @@ -2708,7 +2707,7 @@ else i32.const 0 i32.const 56 - i32.const 34 + i32.const 32 i32.const 2 call $~lib/env/abort unreachable @@ -2819,7 +2818,7 @@ if i32.const 0 i32.const 56 - i32.const 49 + i32.const 47 i32.const 0 call $~lib/env/abort unreachable @@ -2831,7 +2830,7 @@ if i32.const 0 i32.const 56 - i32.const 50 + i32.const 48 i32.const 0 call $~lib/env/abort unreachable @@ -2845,7 +2844,7 @@ if i32.const 0 i32.const 56 - i32.const 51 + i32.const 49 i32.const 0 call $~lib/env/abort unreachable @@ -2857,7 +2856,7 @@ if i32.const 0 i32.const 56 - i32.const 52 + i32.const 50 i32.const 0 call $~lib/env/abort unreachable @@ -2872,7 +2871,7 @@ if i32.const 0 i32.const 56 - i32.const 54 + i32.const 52 i32.const 0 call $~lib/env/abort unreachable @@ -2888,7 +2887,7 @@ if i32.const 0 i32.const 56 - i32.const 56 + i32.const 54 i32.const 0 call $~lib/env/abort unreachable @@ -2905,7 +2904,7 @@ if i32.const 0 i32.const 56 - i32.const 59 + i32.const 57 i32.const 0 call $~lib/env/abort unreachable @@ -2913,8 +2912,6 @@ global.get $std/runtime/barrier1 call $~lib/runtime/index/ALLOC global.set $std/runtime/ref4 - global.get $std/runtime/ref3 - local.set $1 global.get $std/runtime/ref4 local.tee $0 call $~lib/runtime/index/ensureUnregistered @@ -2922,26 +2919,13 @@ i32.store local.get $0 global.set $std/runtime/register_ref - local.get $1 - global.set $std/runtime/register_parentRef global.get $std/runtime/register_ref global.get $std/runtime/ref4 i32.ne if i32.const 0 i32.const 56 - i32.const 63 - i32.const 0 - call $~lib/env/abort - unreachable - end - global.get $std/runtime/register_parentRef - global.get $std/runtime/ref3 - i32.ne - if - i32.const 0 - i32.const 56 - i32.const 64 + i32.const 61 i32.const 0 call $~lib/env/abort unreachable @@ -2957,7 +2941,7 @@ if i32.const 0 i32.const 56 - i32.const 66 + i32.const 63 i32.const 0 call $~lib/env/abort unreachable @@ -2969,7 +2953,7 @@ if i32.const 0 i32.const 56 - i32.const 67 + i32.const 64 i32.const 0 call $~lib/env/abort unreachable @@ -2986,7 +2970,7 @@ if i32.const 0 i32.const 56 - i32.const 70 + i32.const 67 i32.const 0 call $~lib/env/abort unreachable @@ -3002,7 +2986,7 @@ if i32.const 0 i32.const 56 - i32.const 71 + i32.const 68 i32.const 0 call $~lib/env/abort unreachable diff --git a/tests/compiler/std/runtime.ts b/tests/compiler/std/runtime.ts index 08a82443..3b952392 100644 --- a/tests/compiler/std/runtime.ts +++ b/tests/compiler/std/runtime.ts @@ -1,11 +1,9 @@ import "allocator/tlsf"; var register_ref: usize = 0; -var register_parentRef: usize = 0; -@global function __REGISTER_IMPL(ref: usize, parentRef: usize): void { +@global function __REGISTER_IMPL(ref: usize): void { register_ref = ref; - register_parentRef = parentRef; } import { @@ -59,9 +57,8 @@ var ref3 = ALLOC(barrier2); assert(ref1 == ref3); // reuses space of ref1 (free'd in realloc), ref2 (explicitly free'd) var ref4 = ALLOC(barrier1); -REGISTER(ref4, ref3); // sets up ref4 and then calls __REGISTER_IMPL +REGISTER(ref4); // should call __REGISTER_IMPL assert(register_ref == ref4); -assert(register_parentRef == ref3); var header4 = changetype
(register_ref - HEADER_SIZE); assert(header4.classId == __rt_classid()); assert(header4.payloadSize == barrier1); diff --git a/tests/compiler/std/runtime.untouched.wat b/tests/compiler/std/runtime.untouched.wat index 2725add6..c4fd9d9e 100644 --- a/tests/compiler/std/runtime.untouched.wat +++ b/tests/compiler/std/runtime.untouched.wat @@ -37,7 +37,6 @@ (global $~lib/allocator/tlsf/Root.SIZE i32 (i32.const 2916)) (global $~lib/allocator/tlsf/ROOT (mut i32) (i32.const 0)) (global $std/runtime/register_ref (mut i32) (i32.const 0)) - (global $std/runtime/register_parentRef (mut i32) (i32.const 0)) (global $std/runtime/barrier1 (mut i32) (i32.const 0)) (global $std/runtime/barrier2 (mut i32) (i32.const 0)) (global $std/runtime/barrier3 (mut i32) (i32.const 0)) @@ -3393,11 +3392,9 @@ br $~lib/memory/memory.free|inlined.1 end ) - (func $std/runtime/__REGISTER_IMPL (; 31 ;) (type $FUNCSIG$vii) (param $0 i32) (param $1 i32) + (func $std/runtime/__REGISTER_IMPL (; 31 ;) (type $FUNCSIG$vi) (param $0 i32) local.get $0 global.set $std/runtime/register_ref - local.get $1 - global.set $std/runtime/register_parentRef ) (func $~lib/runtime/index/ArrayBufferBase#get:byteLength (; 32 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32) local.get $0 @@ -3415,7 +3412,6 @@ ) (func $start:std/runtime (; 34 ;) (type $FUNCSIG$v) (local $0 i32) - (local $1 i32) call $start:~lib/allocator/tlsf i32.const 43 i32.const 44 @@ -3424,7 +3420,7 @@ if i32.const 0 i32.const 56 - i32.const 26 + i32.const 24 i32.const 0 call $~lib/env/abort unreachable @@ -3437,7 +3433,7 @@ if i32.const 0 i32.const 56 - i32.const 32 + i32.const 30 i32.const 0 call $~lib/env/abort unreachable @@ -3458,7 +3454,7 @@ if i32.const 0 i32.const 56 - i32.const 34 + i32.const 32 i32.const 2 call $~lib/env/abort unreachable @@ -3561,7 +3557,7 @@ if i32.const 0 i32.const 56 - i32.const 49 + i32.const 47 i32.const 0 call $~lib/env/abort unreachable @@ -3574,7 +3570,7 @@ if i32.const 0 i32.const 56 - i32.const 50 + i32.const 48 i32.const 0 call $~lib/env/abort unreachable @@ -3588,7 +3584,7 @@ if i32.const 0 i32.const 56 - i32.const 51 + i32.const 49 i32.const 0 call $~lib/env/abort unreachable @@ -3601,7 +3597,7 @@ if i32.const 0 i32.const 56 - i32.const 52 + i32.const 50 i32.const 0 call $~lib/env/abort unreachable @@ -3617,7 +3613,7 @@ if i32.const 0 i32.const 56 - i32.const 54 + i32.const 52 i32.const 0 call $~lib/env/abort unreachable @@ -3634,7 +3630,7 @@ if i32.const 0 i32.const 56 - i32.const 56 + i32.const 54 i32.const 0 call $~lib/env/abort unreachable @@ -3651,7 +3647,7 @@ if i32.const 0 i32.const 56 - i32.const 59 + i32.const 57 i32.const 0 call $~lib/env/abort unreachable @@ -3662,14 +3658,11 @@ block $~lib/runtime/index/REGISTER|inlined.0 global.get $std/runtime/ref4 local.set $0 - global.get $std/runtime/ref3 - local.set $1 local.get $0 call $~lib/runtime/index/ensureUnregistered i32.const 43 i32.store local.get $0 - local.get $1 call $std/runtime/__REGISTER_IMPL end global.get $std/runtime/register_ref @@ -3679,19 +3672,7 @@ if i32.const 0 i32.const 56 - i32.const 63 - i32.const 0 - call $~lib/env/abort - unreachable - end - global.get $std/runtime/register_parentRef - global.get $std/runtime/ref3 - i32.eq - i32.eqz - if - i32.const 0 - i32.const 56 - i32.const 64 + i32.const 61 i32.const 0 call $~lib/env/abort unreachable @@ -3708,7 +3689,7 @@ if i32.const 0 i32.const 56 - i32.const 66 + i32.const 63 i32.const 0 call $~lib/env/abort unreachable @@ -3721,7 +3702,7 @@ if i32.const 0 i32.const 56 - i32.const 67 + i32.const 64 i32.const 0 call $~lib/env/abort unreachable @@ -3737,7 +3718,7 @@ if i32.const 0 i32.const 56 - i32.const 70 + i32.const 67 i32.const 0 call $~lib/env/abort unreachable @@ -3750,7 +3731,7 @@ if i32.const 0 i32.const 56 - i32.const 71 + i32.const 68 i32.const 0 call $~lib/env/abort unreachable