This commit is contained in:
dcode 2019-03-14 12:46:36 +01:00
parent cdf3e2cf12
commit 3a60638f72
12 changed files with 627 additions and 662 deletions

View File

@ -1,4 +1,5 @@
import { runtime, ArrayBufferView } from "./runtime"; import { runtime, ArrayBufferView } from "./runtime";
import { gc } from "./gc";
import { ArrayBuffer } from "./arraybuffer"; import { ArrayBuffer } from "./arraybuffer";
import { COMPARATOR, SORT } from "./util/sort"; import { COMPARATOR, SORT } from "./util/sort";
import { itoa, dtoa, itoa_stream, dtoa_stream, MAX_DOUBLE_LENGTH } from "./util/number"; import { itoa, dtoa, itoa_stream, dtoa_stream, MAX_DOUBLE_LENGTH } from "./util/number";
@ -76,7 +77,7 @@ export class Array<T> extends ArrayBufferView {
private __set(index: i32, value: T): void { private __set(index: i32, value: T): void {
this.resize(index + 1); this.resize(index + 1);
store<T>(this.dataStart + (<usize>index << alignof<T>()), value); store<T>(this.dataStart + (<usize>index << alignof<T>()), value);
if (isManaged<T>()) runtime.link(changetype<usize>(value), changetype<usize>(this)); if (isManaged<T>()) gc.link(value, this);
if (index >= this.length_) this.length_ = index + 1; if (index >= this.length_) this.length_ = index + 1;
} }
@ -141,7 +142,7 @@ export class Array<T> extends ArrayBufferView {
this.resize(newLength); this.resize(newLength);
this.length_ = newLength; this.length_ = newLength;
store<T>(this.dataStart + (<usize>(newLength - 1) << alignof<T>()), element); store<T>(this.dataStart + (<usize>(newLength - 1) << alignof<T>()), element);
if (isManaged<T>()) runtime.link(changetype<usize>(element), changetype<usize>(this)); if (isManaged<T>()) gc.link(element, this);
return newLength; return newLength;
} }
@ -156,14 +157,14 @@ export class Array<T> extends ArrayBufferView {
for (let offset: usize = 0; offset < thisSize; offset += sizeof<T>()) { for (let offset: usize = 0; offset < thisSize; offset += sizeof<T>()) {
let element = load<T>(thisStart + offset); let element = load<T>(thisStart + offset);
store<T>(outStart + offset, element); store<T>(outStart + offset, element);
runtime.link(changetype<usize>(element), changetype<usize>(out)); gc.link(element, out);
} }
let otherStart = other.dataStart; let otherStart = other.dataStart;
let otherSize = <usize>otherLen << alignof<T>(); let otherSize = <usize>otherLen << alignof<T>();
for (let offset: usize = 0; offset < otherSize; offset += sizeof<T>()) { for (let offset: usize = 0; offset < otherSize; offset += sizeof<T>()) {
let element = load<T>(otherStart + offset); let element = load<T>(otherStart + offset);
store<T>(outStart + thisSize + offset, element); store<T>(outStart + thisSize + offset, element);
runtime.link(changetype<usize>(element), changetype<usize>(out)); gc.link(element, out);
} }
} else { } else {
memory.copy(outStart, this.dataStart, thisSize); memory.copy(outStart, this.dataStart, thisSize);
@ -221,7 +222,7 @@ export class Array<T> extends ArrayBufferView {
let value = load<T>(this.dataStart + (<usize>index << alignof<T>())); let value = load<T>(this.dataStart + (<usize>index << alignof<T>()));
let result = callbackfn(value, index, this); let result = callbackfn(value, index, this);
store<U>(outStart + (<usize>index << alignof<U>()), result); store<U>(outStart + (<usize>index << alignof<U>()), result);
if (isManaged<U>()) runtime.link(changetype<usize>(result), changetype<usize>(out)); if (isManaged<U>()) gc.link(result, out);
} }
return out; return out;
} }
@ -293,7 +294,7 @@ export class Array<T> extends ArrayBufferView {
<usize>(newLength - 1) << alignof<T>() <usize>(newLength - 1) << alignof<T>()
); );
store<T>(base, element); store<T>(base, element);
if (isManaged<T>()) runtime.link(changetype<usize>(element), changetype<usize>(this)); if (isManaged<T>()) gc.link(element, this);
this.length_ = newLength; this.length_ = newLength;
return newLength; return newLength;
} }
@ -310,7 +311,7 @@ export class Array<T> extends ArrayBufferView {
let offset = <usize>i << alignof<T>(); let offset = <usize>i << alignof<T>();
let element = load<T>(thisBase + offset); let element = load<T>(thisBase + offset);
store<T>(sliceBase + offset, element); store<T>(sliceBase + offset, element);
if (isManaged<T>()) runtime.link(changetype<usize>(element), changetype<usize>(slice)); if (isManaged<T>()) gc.link(element, slice);
} }
return slice; return slice;
} }
@ -326,7 +327,7 @@ export class Array<T> extends ArrayBufferView {
for (let i = 0; i < deleteCount; ++i) { for (let i = 0; i < deleteCount; ++i) {
let element = load<T>(thisBase + (<usize>i << alignof<T>())); let element = load<T>(thisBase + (<usize>i << alignof<T>()));
store<T>(spliceStart + (<usize>i << alignof<T>()), element); store<T>(spliceStart + (<usize>i << alignof<T>()), element);
if (isManaged<T>()) runtime.link(changetype<usize>(element), changetype<usize>(splice)); if (isManaged<T>()) gc.link(element, splice);
} }
memory.copy( memory.copy(
splice.dataStart, splice.dataStart,
@ -428,16 +429,17 @@ export class Array<T> extends ArrayBufferView {
if (estLen > offset) { if (estLen > offset) {
let trimmed = changetype<string>(result).substring(0, offset); let trimmed = changetype<string>(result).substring(0, offset);
runtime.free(result); runtime.freeUnregistered(result);
return trimmed; // registered in .substring return trimmed; // registered in .substring
} }
return runtime.register<string>(result); return gc.register<string>(result);
} }
private join_int(separator: string = ","): string { private join_int(separator: string = ","): string {
var lastIndex = this.length_ - 1; var lastIndex = this.length_ - 1;
if (lastIndex < 0) return ""; if (lastIndex < 0) return "";
var dataStart = this.dataStart; var dataStart = this.dataStart;
// @ts-ignore: type
if (!lastIndex) return changetype<string>(itoa<T>(load<T>(dataStart))); if (!lastIndex) return changetype<string>(itoa<T>(load<T>(dataStart)));
var sepLen = separator.length; var sepLen = separator.length;
@ -448,6 +450,7 @@ export class Array<T> extends ArrayBufferView {
var value: T; var value: T;
for (let i = 0; i < lastIndex; ++i) { for (let i = 0; i < lastIndex; ++i) {
value = load<T>(dataStart + (<usize>i << alignof<T>())); value = load<T>(dataStart + (<usize>i << alignof<T>()));
// @ts-ignore: type
offset += itoa_stream<T>(result, offset, value); offset += itoa_stream<T>(result, offset, value);
if (sepLen) { if (sepLen) {
memory.copy( memory.copy(
@ -459,13 +462,14 @@ export class Array<T> extends ArrayBufferView {
} }
} }
value = load<T>(dataStart + (<usize>lastIndex << alignof<T>())); value = load<T>(dataStart + (<usize>lastIndex << alignof<T>()));
// @ts-ignore: type
offset += itoa_stream<T>(result, offset, value); offset += itoa_stream<T>(result, offset, value);
if (estLen > offset) { if (estLen > offset) {
let trimmed = changetype<string>(result).substring(0, offset); let trimmed = changetype<string>(result).substring(0, offset);
runtime.free(result); runtime.freeUnregistered(result);
return trimmed; // registered in .substring return trimmed; // registered in .substring
} }
return runtime.register<string>(result); return gc.register<string>(result);
} }
private join_flt(separator: string = ","): string { private join_flt(separator: string = ","): string {
@ -507,10 +511,10 @@ export class Array<T> extends ArrayBufferView {
); );
if (estLen > offset) { if (estLen > offset) {
let trimmed = changetype<string>(result).substring(0, offset); let trimmed = changetype<string>(result).substring(0, offset);
runtime.free(result); runtime.freeUnregistered(result);
return trimmed; // registered in .substring return trimmed; // registered in .substring
} }
return runtime.register<string>(result); return gc.register<string>(result);
} }
private join_str(separator: string = ","): string { private join_str(separator: string = ","): string {
@ -556,7 +560,7 @@ export class Array<T> extends ArrayBufferView {
<usize>valueLen << 1 <usize>valueLen << 1
); );
} }
return runtime.register<string>(result); return gc.register<string>(result);
} }
private join_arr(separator: string = ","): string { private join_arr(separator: string = ","): string {
@ -625,10 +629,10 @@ export class Array<T> extends ArrayBufferView {
} }
if (estLen > offset) { if (estLen > offset) {
let out = changetype<string>(result).substring(0, offset); let out = changetype<string>(result).substring(0, offset);
runtime.free(result); runtime.freeUnregistered(result);
return out; // registered in .substring return out; // registered in .substring
} }
return runtime.register<string>(result); return gc.register<string>(result);
} }
@inline @inline

View File

@ -1,4 +1,5 @@
import { runtime, ArrayBufferView } from "./runtime"; import { runtime, ArrayBufferView } from "./runtime";
import { gc } from "./gc";
@sealed export class ArrayBuffer { @sealed export class ArrayBuffer {
@ -22,7 +23,9 @@ import { runtime, ArrayBufferView } from "./runtime";
constructor(length: i32) { constructor(length: i32) {
if (<u32>length > <u32>ArrayBufferView.MAX_BYTELENGTH) throw new RangeError("Invalid array buffer length"); if (<u32>length > <u32>ArrayBufferView.MAX_BYTELENGTH) throw new RangeError("Invalid array buffer length");
return runtime.register<ArrayBuffer>(runtime.alloc(<usize>length)); var buffer = runtime.alloc(<usize>length);
memory.fill(changetype<usize>(buffer), 0, <usize>length);
return gc.register<ArrayBuffer>(buffer);
} }
get byteLength(): i32 { get byteLength(): i32 {
@ -34,9 +37,9 @@ import { runtime, ArrayBufferView } from "./runtime";
begin = begin < 0 ? max(length + begin, 0) : min(begin, length); begin = begin < 0 ? max(length + begin, 0) : min(begin, length);
end = end < 0 ? max(length + end , 0) : min(end , length); end = end < 0 ? max(length + end , 0) : min(end , length);
var outSize = <usize>max(end - begin, 0); var outSize = <usize>max(end - begin, 0);
var out = runtime.allocRaw(outSize); var out = runtime.alloc(outSize);
memory.copy(out, changetype<usize>(this) + <usize>begin, outSize); memory.copy(out, changetype<usize>(this) + <usize>begin, outSize);
return runtime.register<ArrayBuffer>(out); return gc.register<ArrayBuffer>(out);
} }
toString(): string { toString(): string {

View File

@ -1,3 +1,5 @@
import { runtime } from "./runtime";
/** Garbage collector interface. */ /** Garbage collector interface. */
export namespace gc { export namespace gc {
@ -21,20 +23,23 @@ export namespace gc {
/** Registers a managed object to be tracked by the garbage collector. */ /** Registers a managed object to be tracked by the garbage collector. */
// @ts-ignore: decorator // @ts-ignore: decorator
@unsafe @unsafe @inline
export function register(ref: usize): void { export function register<T>(ref: usize): T {
runtime.unrefUnregistered(ref).classId = classId<T>();
// @ts-ignore: stub // @ts-ignore: stub
if (isDefined(__gc_register)) __gc_register(ref); if (isDefined(__gc_register)) __gc_register(ref);
else ERROR("missing implementation: gc.register"); return changetype<T>(ref);
} }
/** Links a registered object with the registered object now referencing it. */ /** Links a registered object with the registered object now referencing it. */
// @ts-ignore: decorator // @ts-ignore: decorator
@unsafe @unsafe @inline
export function link(ref: usize, parentRef: usize): void { export function link<T, TParent>(ref: T, parentRef: TParent): void {
assert(changetype<usize>(ref) >= HEAP_BASE + runtime.Header.SIZE); // must be a heap object
var header = changetype<runtime.Header>(changetype<usize>(ref) - runtime.Header.SIZE);
assert(header.classId != runtime.Header.MAGIC && header.gc1 != 0 && header.gc2 != 0); // must be registered
// @ts-ignore: stub // @ts-ignore: stub
if (isDefined(__gc_link)) __gc_link(ref, parentRef); if (isDefined(__gc_link)) __gc_link(ref, parentRef);
else ERROR("missing implementation: gc.link");
} }
/** Marks an object as being reachable. */ /** Marks an object as being reachable. */

View File

@ -1,4 +1,4 @@
import { runtime } from "./runtime"; import { gc } from "./gc";
import { HASH } from "./util/hash"; import { HASH } from "./util/hash";
// A deterministic hash map based on CloseTable from https://github.com/jorendorff/dht // A deterministic hash map based on CloseTable from https://github.com/jorendorff/dht
@ -124,8 +124,8 @@ export class Map<K,V> {
let bucketPtrBase = changetype<usize>(this.buckets) + <usize>(hashCode & this.bucketsMask) * BUCKET_SIZE; let bucketPtrBase = changetype<usize>(this.buckets) + <usize>(hashCode & this.bucketsMask) * BUCKET_SIZE;
entry.taggedNext = load<usize>(bucketPtrBase); entry.taggedNext = load<usize>(bucketPtrBase);
store<usize>(bucketPtrBase, changetype<usize>(entry)); store<usize>(bucketPtrBase, changetype<usize>(entry));
if (isManaged<K>()) runtime.link(changetype<usize>(key), changetype<usize>(this)); if (isManaged<K>()) gc.link(key, this);
if (isManaged<V>()) runtime.link(changetype<usize>(value), changetype<usize>(this)); if (isManaged<V>()) gc.link(value, this);
} }
} }

View File

@ -48,7 +48,7 @@ export namespace runtime {
/** Allocates a new object and returns a pointer to its payload. Does not fill. */ /** Allocates a new object and returns a pointer to its payload. Does not fill. */
// @ts-ignore: decorator // @ts-ignore: decorator
@unsafe @unsafe
export function allocRaw(payloadSize: u32): usize { export function alloc(payloadSize: u32): usize {
var header = changetype<Header>(memory.allocate(adjust(payloadSize))); var header = changetype<Header>(memory.allocate(adjust(payloadSize)));
header.classId = Header.MAGIC; header.classId = Header.MAGIC;
header.payloadSize = payloadSize; header.payloadSize = payloadSize;
@ -59,15 +59,6 @@ export namespace runtime {
return changetype<usize>(header) + Header.SIZE; return changetype<usize>(header) + Header.SIZE;
} }
/** Allocates a new object and returns a pointer to its payload. Fills with zeroes.*/
// @ts-ignore: decorator
@unsafe
export function alloc(payloadSize: u32): usize {
var ref = allocRaw(payloadSize);
memory.fill(ref, 0, payloadSize);
return ref;
}
/** Reallocates an object if necessary. Returns a pointer to its (moved) payload. */ /** Reallocates an object if necessary. Returns a pointer to its (moved) payload. */
// @ts-ignore: decorator // @ts-ignore: decorator
@unsafe @unsafe
@ -83,7 +74,7 @@ export namespace runtime {
if (select(adjust(payloadSize), 0, ref > HEAP_BASE) < newAdjustedSize) { if (select(adjust(payloadSize), 0, ref > HEAP_BASE) < newAdjustedSize) {
// move if the allocation isn't large enough or not a heap object // move if the allocation isn't large enough or not a heap object
let newHeader = changetype<Header>(memory.allocate(newAdjustedSize)); let newHeader = changetype<Header>(memory.allocate(newAdjustedSize));
newHeader.classId = Header.MAGIC; newHeader.classId = header.classId;
if (gc.implemented) { if (gc.implemented) {
newHeader.gc1 = 0; newHeader.gc1 = 0;
newHeader.gc2 = 0; newHeader.gc2 = 0;
@ -97,7 +88,8 @@ export namespace runtime {
memory.free(changetype<usize>(header)); memory.free(changetype<usize>(header));
} else if (gc.implemented) { } else if (gc.implemented) {
// if previously registered, register again // if previously registered, register again
gc.register(ref); // @ts-ignore: stub
__gc_register(ref);
} }
header = newHeader; header = newHeader;
ref = newRef; ref = newRef;
@ -113,40 +105,20 @@ export namespace runtime {
return ref; return ref;
} }
function unref(ref: usize): Header { // @ts-ignore: decorator
@unsafe
export function unrefUnregistered(ref: usize): Header {
assert(ref >= HEAP_BASE + Header.SIZE); // must be a heap object assert(ref >= HEAP_BASE + Header.SIZE); // must be a heap object
var header = changetype<Header>(ref - Header.SIZE); var header = changetype<Header>(ref - Header.SIZE);
assert(header.classId == Header.MAGIC); // must be unregistered assert(header.classId == Header.MAGIC); // must be unregistered
return header; return header;
} }
/** Frees an object. Must not have been registered with GC yet. */ /** Frees an unregistered object that turned out to be unnecessary. */
// @ts-ignore: decorator // @ts-ignore: decorator
@unsafe @inline @unsafe @inline
export function free<T>(ref: T): void { export function freeUnregistered<T>(ref: T): void {
memory.free(changetype<usize>(unref(changetype<usize>(ref)))); memory.free(changetype<usize>(unrefUnregistered(changetype<usize>(ref))));
}
/** Registers a managed object. Cannot be free'd anymore afterwards. */
// @ts-ignore: decorator
@unsafe @inline
export function register<T>(ref: usize): T {
if (!isReference<T>()) 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<T>();
if (gc.implemented) gc.register(ref);
return changetype<T>(ref);
}
/** Links a managed object with its managed parent. */
// @ts-ignore: decorator
@unsafe @inline
export function link<T, TParent>(ref: T, parentRef: TParent): void {
assert(changetype<usize>(ref) >= HEAP_BASE + Header.SIZE); // must be a heap object
var header = changetype<Header>(changetype<usize>(ref) - Header.SIZE);
assert(header.classId != Header.MAGIC && header.gc1 != 0 && header.gc2 != 0); // must be registered
if (gc.implemented) gc.link(changetype<usize>(ref), changetype<usize>(parentRef)); // tslint:disable-line
} }
} }

View File

@ -1,4 +1,4 @@
import { runtime } from "./runtime"; import { gc } from "./gc";
import { HASH } from "./util/hash"; import { HASH } from "./util/hash";
// A deterministic hash set based on CloseTable from https://github.com/jorendorff/dht // A deterministic hash set based on CloseTable from https://github.com/jorendorff/dht
@ -70,7 +70,7 @@ export class Set<K> {
this.buckets = new ArrayBuffer(bucketsSize); this.buckets = new ArrayBuffer(bucketsSize);
this.bucketsMask = INITIAL_CAPACITY - 1; this.bucketsMask = INITIAL_CAPACITY - 1;
const entriesSize = INITIAL_CAPACITY * <i32>ENTRY_SIZE<K>(); const entriesSize = INITIAL_CAPACITY * <i32>ENTRY_SIZE<K>();
this.entries = new ArrayBuffer(entriesSize, true); this.entries = new ArrayBuffer(entriesSize);
this.entriesCapacity = INITIAL_CAPACITY; this.entriesCapacity = INITIAL_CAPACITY;
this.entriesOffset = 0; this.entriesOffset = 0;
this.entriesCount = 0; this.entriesCount = 0;
@ -114,7 +114,7 @@ export class Set<K> {
let bucketPtrBase = changetype<usize>(this.buckets) + <usize>(hashCode & this.bucketsMask) * BUCKET_SIZE; let bucketPtrBase = changetype<usize>(this.buckets) + <usize>(hashCode & this.bucketsMask) * BUCKET_SIZE;
entry.taggedNext = load<usize>(bucketPtrBase); entry.taggedNext = load<usize>(bucketPtrBase);
store<usize>(bucketPtrBase, changetype<usize>(entry)); store<usize>(bucketPtrBase, changetype<usize>(entry));
if (isManaged<K>()) runtime.link(changetype<usize>(key), changetype<usize>(this)); // tslint:disable-line if (isManaged<K>()) gc.link(key, this);
} }
} }
@ -136,7 +136,7 @@ export class Set<K> {
var newBucketsCapacity = <i32>(newBucketsMask + 1); var newBucketsCapacity = <i32>(newBucketsMask + 1);
var newBuckets = new ArrayBuffer(newBucketsCapacity * <i32>BUCKET_SIZE); var newBuckets = new ArrayBuffer(newBucketsCapacity * <i32>BUCKET_SIZE);
var newEntriesCapacity = <i32>(newBucketsCapacity * FILL_FACTOR); var newEntriesCapacity = <i32>(newBucketsCapacity * FILL_FACTOR);
var newEntries = new ArrayBuffer(newEntriesCapacity * <i32>ENTRY_SIZE<K>(), true); var newEntries = new ArrayBuffer(newEntriesCapacity * <i32>ENTRY_SIZE<K>());
// copy old entries to new entries // copy old entries to new entries
var oldPtr = changetype<usize>(this.entries); var oldPtr = changetype<usize>(this.entries);

View File

@ -1,4 +1,5 @@
import { runtime } from "./runtime"; import { runtime } from "./runtime";
import { gc } from "./gc";
import { MAX_SIZE_32 } from "./util/allocator"; import { MAX_SIZE_32 } from "./util/allocator";
import { compareImpl, parse, CharCode, isWhiteSpaceOrLineTerminator } from "./util/string"; import { compareImpl, parse, CharCode, isWhiteSpaceOrLineTerminator } from "./util/string";
@ -14,15 +15,15 @@ import { compareImpl, parse, CharCode, isWhiteSpaceOrLineTerminator } from "./ut
// TODO Add and handle second argument // TODO Add and handle second argument
static fromCharCode(code: i32): String { static fromCharCode(code: i32): String {
var out = runtime.allocRaw(2); var out = runtime.alloc(2);
store<u16>(out, <u16>code); store<u16>(out, <u16>code);
return runtime.register<String>(out); return gc.register<String>(out);
} }
static fromCodePoint(code: i32): String { static fromCodePoint(code: i32): String {
assert(<u32>code <= 0x10FFFF); assert(<u32>code <= 0x10FFFF);
var sur = code > 0xFFFF; var sur = code > 0xFFFF;
var out = runtime.allocRaw((i32(sur) + 1) << 1); var out = runtime.alloc((i32(sur) + 1) << 1);
if (!sur) { if (!sur) {
store<u16>(out, <u16>code); store<u16>(out, <u16>code);
} else { } else {
@ -31,15 +32,15 @@ import { compareImpl, parse, CharCode, isWhiteSpaceOrLineTerminator } from "./ut
let lo: u32 = (code & 0x3FF) + 0xDC00; let lo: u32 = (code & 0x3FF) + 0xDC00;
store<u32>(out, (hi << 16) | lo); store<u32>(out, (hi << 16) | lo);
} }
return runtime.register<String>(out); return gc.register<String>(out);
} }
@operator("[]") charAt(pos: i32): String { @operator("[]") charAt(pos: i32): String {
assert(this !== null); assert(this !== null);
if (<u32>pos >= <u32>this.length) return changetype<String>(""); if (<u32>pos >= <u32>this.length) return changetype<String>("");
var out = runtime.allocRaw(2); var out = runtime.alloc(2);
store<u16>(out, load<u16>(changetype<usize>(this) + (<usize>pos << 1))); store<u16>(out, load<u16>(changetype<usize>(this) + (<usize>pos << 1)));
return runtime.register<String>(out); return gc.register<String>(out);
} }
charCodeAt(pos: i32): i32 { charCodeAt(pos: i32): i32 {
@ -70,10 +71,10 @@ import { compareImpl, parse, CharCode, isWhiteSpaceOrLineTerminator } from "./ut
var otherSize: isize = other.length << 1; var otherSize: isize = other.length << 1;
var outSize: usize = thisSize + otherSize; var outSize: usize = thisSize + otherSize;
if (outSize == 0) return changetype<String>(""); if (outSize == 0) return changetype<String>("");
var out = runtime.allocRaw(outSize); var out = runtime.alloc(outSize);
memory.copy(out, changetype<usize>(this), thisSize); memory.copy(out, changetype<usize>(this), thisSize);
memory.copy(out + thisSize, changetype<usize>(other), otherSize); memory.copy(out + thisSize, changetype<usize>(other), otherSize);
return runtime.register<String>(out); return gc.register<String>(out);
} }
endsWith(searchString: String, endPosition: i32 = String.MAX_LENGTH): bool { endsWith(searchString: String, endPosition: i32 = String.MAX_LENGTH): bool {
@ -183,9 +184,9 @@ import { compareImpl, parse, CharCode, isWhiteSpaceOrLineTerminator } from "./ut
if (intStart < 0) intStart = max(size + intStart, 0); if (intStart < 0) intStart = max(size + intStart, 0);
var resultLength = min(max(end, 0), size - intStart); var resultLength = min(max(end, 0), size - intStart);
if (resultLength <= 0) return changetype<String>(""); if (resultLength <= 0) return changetype<String>("");
var out = runtime.allocRaw(resultLength << 1); var out = runtime.alloc(resultLength << 1);
memory.copy(out, changetype<usize>(this) + intStart, resultLength); memory.copy(out, changetype<usize>(this) + intStart, resultLength);
return runtime.register<String>(out); return gc.register<String>(out);
} }
substring(start: i32, end: i32 = i32.MAX_VALUE): String { substring(start: i32, end: i32 = i32.MAX_VALUE): String {
@ -198,9 +199,9 @@ import { compareImpl, parse, CharCode, isWhiteSpaceOrLineTerminator } from "./ut
len = toPos - fromPos; len = toPos - fromPos;
if (!len) return changetype<String>(""); if (!len) return changetype<String>("");
if (!fromPos && toPos == this.length << 1) return this; if (!fromPos && toPos == this.length << 1) return this;
var out = runtime.allocRaw(len); var out = runtime.alloc(len);
memory.copy(out, changetype<usize>(this) + fromPos, len); memory.copy(out, changetype<usize>(this) + fromPos, len);
return runtime.register<String>(out); return gc.register<String>(out);
} }
trim(): String { trim(): String {
@ -226,9 +227,9 @@ import { compareImpl, parse, CharCode, isWhiteSpaceOrLineTerminator } from "./ut
} }
if (!size) return changetype<String>(""); if (!size) return changetype<String>("");
if (!start && size == length << 1) return this; if (!start && size == length << 1) return this;
var out = runtime.allocRaw(size); var out = runtime.alloc(size);
memory.copy(out, changetype<usize>(this) + offset, size); memory.copy(out, changetype<usize>(this) + offset, size);
return runtime.register<String>(out); return gc.register<String>(out);
} }
@inline @inline
@ -256,9 +257,9 @@ import { compareImpl, parse, CharCode, isWhiteSpaceOrLineTerminator } from "./ut
if (!offset) return this; if (!offset) return this;
size -= offset; size -= offset;
if (!size) return changetype<String>(""); if (!size) return changetype<String>("");
var out = runtime.allocRaw(size); var out = runtime.alloc(size);
memory.copy(out, changetype<usize>(this) + offset, size); memory.copy(out, changetype<usize>(this) + offset, size);
return runtime.register<String>(out); return gc.register<String>(out);
} }
trimEnd(): String { trimEnd(): String {
@ -275,9 +276,9 @@ import { compareImpl, parse, CharCode, isWhiteSpaceOrLineTerminator } from "./ut
} }
if (!size) return changetype<String>(""); if (!size) return changetype<String>("");
if (size == originalSize) return this; if (size == originalSize) return this;
var out = runtime.allocRaw(size); var out = runtime.alloc(size);
memory.copy(out, changetype<usize>(this), size); memory.copy(out, changetype<usize>(this), size);
return runtime.register<String>(out); return gc.register<String>(out);
} }
padStart(targetLength: i32, padString: string = " "): String { padStart(targetLength: i32, padString: string = " "): String {
@ -287,7 +288,7 @@ import { compareImpl, parse, CharCode, isWhiteSpaceOrLineTerminator } from "./ut
var padSize = <usize>padString.length << 1; var padSize = <usize>padString.length << 1;
if (targetSize < thisSize || !padSize) return this; if (targetSize < thisSize || !padSize) return this;
var prependSize = targetSize - thisSize; var prependSize = targetSize - thisSize;
var out = runtime.allocRaw(targetSize); var out = runtime.alloc(targetSize);
if (prependSize > padSize) { if (prependSize > padSize) {
let repeatCount = (prependSize - 2) / padSize; let repeatCount = (prependSize - 2) / padSize;
let restBase = repeatCount * padSize; let restBase = repeatCount * padSize;
@ -298,7 +299,7 @@ import { compareImpl, parse, CharCode, isWhiteSpaceOrLineTerminator } from "./ut
memory.copy(out, changetype<usize>(padString), prependSize); memory.copy(out, changetype<usize>(padString), prependSize);
} }
memory.copy(out + prependSize, changetype<usize>(this), thisSize); memory.copy(out + prependSize, changetype<usize>(this), thisSize);
return runtime.register<String>(out); return gc.register<String>(out);
} }
padEnd(targetLength: i32, padString: string = " "): String { padEnd(targetLength: i32, padString: string = " "): String {
@ -308,7 +309,7 @@ import { compareImpl, parse, CharCode, isWhiteSpaceOrLineTerminator } from "./ut
var padSize = <usize>padString.length << 1; var padSize = <usize>padString.length << 1;
if (targetSize < thisSize || !padSize) return this; if (targetSize < thisSize || !padSize) return this;
var appendSize = targetSize - thisSize; var appendSize = targetSize - thisSize;
var out = runtime.allocRaw(targetSize); var out = runtime.alloc(targetSize);
memory.copy(out, changetype<usize>(this), thisSize); memory.copy(out, changetype<usize>(this), thisSize);
if (appendSize > padSize) { if (appendSize > padSize) {
let repeatCount = (appendSize - 2) / padSize; let repeatCount = (appendSize - 2) / padSize;
@ -319,7 +320,7 @@ import { compareImpl, parse, CharCode, isWhiteSpaceOrLineTerminator } from "./ut
} else { } else {
memory.copy(out + thisSize, changetype<usize>(padString), appendSize); memory.copy(out + thisSize, changetype<usize>(padString), appendSize);
} }
return runtime.register<String>(out); return gc.register<String>(out);
} }
repeat(count: i32 = 0): String { repeat(count: i32 = 0): String {
@ -333,9 +334,9 @@ import { compareImpl, parse, CharCode, isWhiteSpaceOrLineTerminator } from "./ut
if (count == 0 || !length) return changetype<String>(""); if (count == 0 || !length) return changetype<String>("");
if (count == 1) return this; if (count == 1) return this;
var out = runtime.allocRaw((length * count) << 1); var out = runtime.alloc((length * count) << 1);
memory.repeat(out, changetype<usize>(this), <usize>length << 1, count); memory.repeat(out, changetype<usize>(this), <usize>length << 1, count);
return runtime.register<String>(out); return gc.register<String>(out);
} }
slice(beginIndex: i32, endIndex: i32 = i32.MAX_VALUE): String { slice(beginIndex: i32, endIndex: i32 = i32.MAX_VALUE): String {
@ -344,9 +345,9 @@ import { compareImpl, parse, CharCode, isWhiteSpaceOrLineTerminator } from "./ut
var end = endIndex < 0 ? max(endIndex + len, 0) : min(endIndex, len); var end = endIndex < 0 ? max(endIndex + len, 0) : min(endIndex, len);
len = end - begin; len = end - begin;
if (len <= 0) return changetype<String>(""); if (len <= 0) return changetype<String>("");
var out = runtime.allocRaw(len << 1); var out = runtime.alloc(len << 1);
memory.copy(out, changetype<usize>(this) + (<usize>begin << 1), <usize>len << 1); memory.copy(out, changetype<usize>(this) + (<usize>begin << 1), <usize>len << 1);
return runtime.register<String>(out); return gc.register<String>(out);
} }
split(separator: String | null = null, limit: i32 = i32.MAX_VALUE): String[] { split(separator: String | null = null, limit: i32 = i32.MAX_VALUE): String[] {
@ -364,7 +365,7 @@ import { compareImpl, parse, CharCode, isWhiteSpaceOrLineTerminator } from "./ut
let buffer = unreachable(); // TODO let buffer = unreachable(); // TODO
// let buffer = <ArrayBuffer>result.buffer_; // let buffer = <ArrayBuffer>result.buffer_;
for (let i: isize = 0; i < length; ++i) { for (let i: isize = 0; i < length; ++i) {
let char = runtime.allocRaw(2); let char = runtime.alloc(2);
store<u16>( store<u16>(
changetype<usize>(char), changetype<usize>(char),
load<u16>( load<u16>(
@ -384,9 +385,9 @@ import { compareImpl, parse, CharCode, isWhiteSpaceOrLineTerminator } from "./ut
while ((end = this.indexOf(separator!, start)) != -1) { while ((end = this.indexOf(separator!, start)) != -1) {
let len = end - start; let len = end - start;
if (len > 0) { if (len > 0) {
let out = runtime.allocRaw(<usize>len << 1); let out = runtime.alloc(<usize>len << 1);
memory.copy(out, changetype<usize>(this) + (<usize>start << 1), <usize>len << 1); memory.copy(out, changetype<usize>(this) + (<usize>start << 1), <usize>len << 1);
result.push(runtime.register<String>(out)); result.push(gc.register<String>(out));
} else { } else {
result.push(changetype<String>("")); result.push(changetype<String>(""));
} }
@ -400,9 +401,9 @@ import { compareImpl, parse, CharCode, isWhiteSpaceOrLineTerminator } from "./ut
} }
var len = length - start; var len = length - start;
if (len > 0) { if (len > 0) {
let out = runtime.allocRaw(<usize>len << 1); let out = runtime.alloc(<usize>len << 1);
memory.copy(out, changetype<usize>(this) + (<usize>start << 1), <usize>len << 1); memory.copy(out, changetype<usize>(this) + (<usize>start << 1), <usize>len << 1);
result.push(runtime.register<String>(out)); result.push(gc.register<String>(out));
} else { } else {
result.push(changetype<String>("")); result.push(changetype<String>(""));
} }
@ -474,10 +475,10 @@ import { compareImpl, parse, CharCode, isWhiteSpaceOrLineTerminator } from "./ut
} }
} }
assert(ptrPos == len); assert(ptrPos == len);
var out = runtime.allocRaw(bufPos); var out = runtime.alloc(bufPos);
memory.copy(changetype<usize>(out), buf, bufPos); memory.copy(changetype<usize>(out), buf, bufPos);
memory.free(buf); memory.free(buf);
return runtime.register<string>(out); return gc.register<string>(out);
} }
toUTF8(): usize { toUTF8(): usize {

View File

@ -1,4 +1,5 @@
import { runtime, ArrayBufferView } from "./runtime"; import { runtime, ArrayBufferView } from "./runtime";
import { gc } from "./gc";
import { COMPARATOR, SORT as SORT_IMPL } from "./util/sort"; import { COMPARATOR, SORT as SORT_IMPL } from "./util/sort";
function clampToByte(value: i32): i32 { function clampToByte(value: i32): i32 {
@ -759,11 +760,11 @@ function SUBARRAY<TArray extends ArrayBufferView, T>(
else begin = min(begin, length); else begin = min(begin, length);
if (end < 0) end = max(length + end, begin); if (end < 0) end = max(length + end, begin);
else end = max(min(end, length), begin); else end = max(min(end, length), begin);
var out = runtime.allocRaw(offsetof<TArray>()); var out = runtime.alloc(offsetof<TArray>());
store<usize>(out, buffer, offsetof<TArray>("buffer")); store<usize>(out, buffer, offsetof<TArray>("buffer"));
store<usize>(out, array.dataStart + (<usize>begin << alignof<T>()) , offsetof<TArray>("dataStart")); store<usize>(out, array.dataStart + (<usize>begin << alignof<T>()) , offsetof<TArray>("dataStart"));
store<usize>(out, array.dataEnd + (<usize>(end - begin) << alignof<T>()), offsetof<TArray>("dataEnd")); store<usize>(out, array.dataEnd + (<usize>(end - begin) << alignof<T>()), offsetof<TArray>("dataEnd"));
runtime.link(buffer, runtime.register<TArray>(out)); // register first, then link gc.link(buffer, gc.register<TArray>(out)); // register first, then link
return changetype<TArray>(out); return changetype<TArray>(out);
} }

View File

@ -1,4 +1,5 @@
import { runtime, ArrayBufferView } from "../runtime"; import { runtime, ArrayBufferView } from "../runtime";
import { gc } from "../gc";
import { CharCode } from "./string"; import { CharCode } from "./string";
// @ts-ignore: decorator // @ts-ignore: decorator
@ -265,7 +266,7 @@ export function utoa32(value: u32): String {
var out = runtime.alloc(decimals << 1); var out = runtime.alloc(decimals << 1);
utoa32_core(changetype<usize>(out), value, decimals); utoa32_core(changetype<usize>(out), value, decimals);
return runtime.register<String>(out); return gc.register<String>(out);
} }
export function itoa32(value: i32): String { export function itoa32(value: i32): String {
@ -280,7 +281,7 @@ export function itoa32(value: i32): String {
utoa32_core(changetype<usize>(out), value, decimals); utoa32_core(changetype<usize>(out), value, decimals);
if (sign) store<u16>(changetype<usize>(out), CharCode.MINUS); if (sign) store<u16>(changetype<usize>(out), CharCode.MINUS);
return runtime.register<String>(out); return gc.register<String>(out);
} }
export function utoa64(value: u64): String { export function utoa64(value: u64): String {
@ -297,7 +298,7 @@ export function utoa64(value: u64): String {
out = runtime.alloc(decimals << 1); out = runtime.alloc(decimals << 1);
utoa64_core(changetype<usize>(out), value, decimals); utoa64_core(changetype<usize>(out), value, decimals);
} }
return runtime.register<String>(out); return gc.register<String>(out);
} }
export function itoa64(value: i64): String { export function itoa64(value: i64): String {
@ -319,7 +320,7 @@ export function itoa64(value: i64): String {
} }
if (sign) store<u16>(changetype<usize>(out), CharCode.MINUS); if (sign) store<u16>(changetype<usize>(out), CharCode.MINUS);
return runtime.register<String>(out); return gc.register<String>(out);
} }
export function itoa<T extends number>(value: T): String { export function itoa<T extends number>(value: T): String {
@ -627,7 +628,7 @@ export function dtoa(value: f64): String {
var temp = runtime.alloc(MAX_DOUBLE_LENGTH << 1); var temp = runtime.alloc(MAX_DOUBLE_LENGTH << 1);
var length = dtoa_core(temp, value); var length = dtoa_core(temp, value);
var result = changetype<String>(temp).substring(0, length); var result = changetype<String>(temp).substring(0, length);
runtime.free(temp); runtime.freeUnregistered(temp);
return result; return result;
} }

View File

@ -1170,7 +1170,7 @@
local.get $0 local.get $0
call $~lib/allocator/tlsf/Root#use call $~lib/allocator/tlsf/Root#use
) )
(func $~lib/runtime/runtime.allocRaw (; 17 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32) (func $~lib/runtime/runtime.alloc (; 17 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
(local $1 i32) (local $1 i32)
i32.const 1 i32.const 1
i32.const 32 i32.const 32
@ -1197,240 +1197,7 @@
i32.const 16 i32.const 16
i32.add i32.add
) )
(func $~lib/util/memory/memset (; 18 ;) (type $FUNCSIG$vii) (param $0 i32) (param $1 i32) (func $~lib/util/memory/memcpy (; 18 ;) (type $FUNCSIG$viii) (param $0 i32) (param $1 i32) (param $2 i32)
(local $2 i32)
local.get $1
i32.eqz
if
return
end
local.get $0
i32.const 0
i32.store8
local.get $0
local.get $1
i32.add
i32.const 1
i32.sub
i32.const 0
i32.store8
local.get $1
i32.const 2
i32.le_u
if
return
end
local.get $0
i32.const 1
i32.add
i32.const 0
i32.store8
local.get $0
i32.const 2
i32.add
i32.const 0
i32.store8
local.get $0
local.get $1
i32.add
local.tee $2
i32.const 2
i32.sub
i32.const 0
i32.store8
local.get $2
i32.const 3
i32.sub
i32.const 0
i32.store8
local.get $1
i32.const 6
i32.le_u
if
return
end
local.get $0
i32.const 3
i32.add
i32.const 0
i32.store8
local.get $0
local.get $1
i32.add
i32.const 4
i32.sub
i32.const 0
i32.store8
local.get $1
i32.const 8
i32.le_u
if
return
end
i32.const 0
local.get $0
i32.sub
i32.const 3
i32.and
local.tee $2
local.get $0
i32.add
local.tee $0
i32.const 0
i32.store
local.get $1
local.get $2
i32.sub
i32.const -4
i32.and
local.tee $1
local.get $0
i32.add
i32.const 4
i32.sub
i32.const 0
i32.store
local.get $1
i32.const 8
i32.le_u
if
return
end
local.get $0
i32.const 4
i32.add
i32.const 0
i32.store
local.get $0
i32.const 8
i32.add
i32.const 0
i32.store
local.get $0
local.get $1
i32.add
local.tee $2
i32.const 12
i32.sub
i32.const 0
i32.store
local.get $2
i32.const 8
i32.sub
i32.const 0
i32.store
local.get $1
i32.const 24
i32.le_u
if
return
end
local.get $0
i32.const 12
i32.add
i32.const 0
i32.store
local.get $0
i32.const 16
i32.add
i32.const 0
i32.store
local.get $0
i32.const 20
i32.add
i32.const 0
i32.store
local.get $0
i32.const 24
i32.add
i32.const 0
i32.store
local.get $0
local.get $1
i32.add
local.tee $2
i32.const 28
i32.sub
i32.const 0
i32.store
local.get $2
i32.const 24
i32.sub
i32.const 0
i32.store
local.get $2
i32.const 20
i32.sub
i32.const 0
i32.store
local.get $2
i32.const 16
i32.sub
i32.const 0
i32.store
local.get $0
i32.const 4
i32.and
i32.const 24
i32.add
local.tee $2
local.get $0
i32.add
local.set $0
local.get $1
local.get $2
i32.sub
local.set $1
loop $continue|0
local.get $1
i32.const 32
i32.ge_u
if
local.get $0
i64.const 0
i64.store
local.get $0
i32.const 8
i32.add
i64.const 0
i64.store
local.get $0
i32.const 16
i32.add
i64.const 0
i64.store
local.get $0
i32.const 24
i32.add
i64.const 0
i64.store
local.get $1
i32.const 32
i32.sub
local.set $1
local.get $0
i32.const 32
i32.add
local.set $0
br $continue|0
end
end
)
(func $~lib/memory/memory.fill (; 19 ;) (type $FUNCSIG$vii) (param $0 i32) (param $1 i32)
local.get $0
local.get $1
call $~lib/util/memory/memset
)
(func $~lib/runtime/runtime.alloc (; 20 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
(local $1 i32)
local.get $0
call $~lib/runtime/runtime.allocRaw
local.tee $1
local.get $0
call $~lib/memory/memory.fill
local.get $1
)
(func $~lib/util/memory/memcpy (; 21 ;) (type $FUNCSIG$viii) (param $0 i32) (param $1 i32) (param $2 i32)
(local $3 i32) (local $3 i32)
(local $4 i32) (local $4 i32)
(local $5 i32) (local $5 i32)
@ -2327,7 +2094,7 @@
i32.store8 i32.store8
end end
) )
(func $~lib/util/memory/memmove (; 22 ;) (type $FUNCSIG$viii) (param $0 i32) (param $1 i32) (param $2 i32) (func $~lib/util/memory/memmove (; 19 ;) (type $FUNCSIG$viii) (param $0 i32) (param $1 i32) (param $2 i32)
(local $3 i32) (local $3 i32)
(local $4 i32) (local $4 i32)
local.get $0 local.get $0
@ -2525,7 +2292,231 @@
end end
end end
) )
(func $~lib/allocator/tlsf/__memory_free (; 23 ;) (type $FUNCSIG$vi) (param $0 i32) (func $~lib/util/memory/memset (; 20 ;) (type $FUNCSIG$vii) (param $0 i32) (param $1 i32)
(local $2 i32)
local.get $1
i32.eqz
if
return
end
local.get $0
i32.const 0
i32.store8
local.get $0
local.get $1
i32.add
i32.const 1
i32.sub
i32.const 0
i32.store8
local.get $1
i32.const 2
i32.le_u
if
return
end
local.get $0
i32.const 1
i32.add
i32.const 0
i32.store8
local.get $0
i32.const 2
i32.add
i32.const 0
i32.store8
local.get $0
local.get $1
i32.add
local.tee $2
i32.const 2
i32.sub
i32.const 0
i32.store8
local.get $2
i32.const 3
i32.sub
i32.const 0
i32.store8
local.get $1
i32.const 6
i32.le_u
if
return
end
local.get $0
i32.const 3
i32.add
i32.const 0
i32.store8
local.get $0
local.get $1
i32.add
i32.const 4
i32.sub
i32.const 0
i32.store8
local.get $1
i32.const 8
i32.le_u
if
return
end
i32.const 0
local.get $0
i32.sub
i32.const 3
i32.and
local.tee $2
local.get $0
i32.add
local.tee $0
i32.const 0
i32.store
local.get $1
local.get $2
i32.sub
i32.const -4
i32.and
local.tee $1
local.get $0
i32.add
i32.const 4
i32.sub
i32.const 0
i32.store
local.get $1
i32.const 8
i32.le_u
if
return
end
local.get $0
i32.const 4
i32.add
i32.const 0
i32.store
local.get $0
i32.const 8
i32.add
i32.const 0
i32.store
local.get $0
local.get $1
i32.add
local.tee $2
i32.const 12
i32.sub
i32.const 0
i32.store
local.get $2
i32.const 8
i32.sub
i32.const 0
i32.store
local.get $1
i32.const 24
i32.le_u
if
return
end
local.get $0
i32.const 12
i32.add
i32.const 0
i32.store
local.get $0
i32.const 16
i32.add
i32.const 0
i32.store
local.get $0
i32.const 20
i32.add
i32.const 0
i32.store
local.get $0
i32.const 24
i32.add
i32.const 0
i32.store
local.get $0
local.get $1
i32.add
local.tee $2
i32.const 28
i32.sub
i32.const 0
i32.store
local.get $2
i32.const 24
i32.sub
i32.const 0
i32.store
local.get $2
i32.const 20
i32.sub
i32.const 0
i32.store
local.get $2
i32.const 16
i32.sub
i32.const 0
i32.store
local.get $0
i32.const 4
i32.and
i32.const 24
i32.add
local.tee $2
local.get $0
i32.add
local.set $0
local.get $1
local.get $2
i32.sub
local.set $1
loop $continue|0
local.get $1
i32.const 32
i32.ge_u
if
local.get $0
i64.const 0
i64.store
local.get $0
i32.const 8
i32.add
i64.const 0
i64.store
local.get $0
i32.const 16
i32.add
i64.const 0
i64.store
local.get $0
i32.const 24
i32.add
i64.const 0
i64.store
local.get $1
i32.const 32
i32.sub
local.set $1
local.get $0
i32.const 32
i32.add
local.set $0
br $continue|0
end
end
)
(func $~lib/memory/memory.fill (; 21 ;) (type $FUNCSIG$vii) (param $0 i32) (param $1 i32)
local.get $0
local.get $1
call $~lib/util/memory/memset
)
(func $~lib/allocator/tlsf/__memory_free (; 22 ;) (type $FUNCSIG$vi) (param $0 i32)
(local $1 i32) (local $1 i32)
(local $2 i32) (local $2 i32)
(local $3 i32) (local $3 i32)
@ -2563,7 +2554,7 @@
end end
end end
) )
(func $~lib/runtime/runtime.realloc (; 24 ;) (type $FUNCSIG$iii) (param $0 i32) (param $1 i32) (result i32) (func $~lib/runtime/runtime.realloc (; 23 ;) (type $FUNCSIG$iii) (param $0 i32) (param $1 i32) (result i32)
(local $2 i32) (local $2 i32)
(local $3 i32) (local $3 i32)
(local $4 i32) (local $4 i32)
@ -2604,7 +2595,8 @@
local.get $4 local.get $4
call $~lib/allocator/tlsf/__memory_allocate call $~lib/allocator/tlsf/__memory_allocate
local.tee $5 local.tee $5
i32.const -1520547049 local.get $3
i32.load
i32.store i32.store
local.get $5 local.get $5
i32.const 0 i32.const 0
@ -2637,7 +2629,7 @@
if if
i32.const 0 i32.const 0
i32.const 184 i32.const 184
i32.const 96 i32.const 87
i32.const 10 i32.const 10
call $~lib/env/abort call $~lib/env/abort
unreachable unreachable
@ -2667,14 +2659,14 @@
i32.store offset=4 i32.store offset=4
local.get $0 local.get $0
) )
(func $~lib/runtime/runtime.unref (; 25 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32) (func $~lib/runtime/runtime.unrefUnregistered (; 24 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
local.get $0 local.get $0
i32.const 232 i32.const 232
i32.lt_u i32.lt_u
if if
i32.const 0 i32.const 0
i32.const 184 i32.const 184
i32.const 117 i32.const 111
i32.const 4 i32.const 4
call $~lib/env/abort call $~lib/env/abort
unreachable unreachable
@ -2689,14 +2681,14 @@
if if
i32.const 0 i32.const 0
i32.const 184 i32.const 184
i32.const 119 i32.const 113
i32.const 4 i32.const 4
call $~lib/env/abort call $~lib/env/abort
unreachable unreachable
end end
local.get $0 local.get $0
) )
(func $start:std/runtime (; 26 ;) (type $FUNCSIG$v) (func $start:std/runtime (; 25 ;) (type $FUNCSIG$v)
(local $0 i32) (local $0 i32)
(local $1 i32) (local $1 i32)
(local $2 i32) (local $2 i32)
@ -2924,7 +2916,7 @@
unreachable unreachable
end end
global.get $std/runtime/ref2 global.get $std/runtime/ref2
call $~lib/runtime/runtime.unref call $~lib/runtime/runtime.unrefUnregistered
call $~lib/allocator/tlsf/__memory_free call $~lib/allocator/tlsf/__memory_free
global.get $std/runtime/barrier2 global.get $std/runtime/barrier2
call $~lib/runtime/runtime.alloc call $~lib/runtime/runtime.alloc
@ -2945,7 +2937,7 @@
global.set $std/runtime/ref4 global.set $std/runtime/ref4
global.get $std/runtime/ref4 global.get $std/runtime/ref4
local.tee $0 local.tee $0
call $~lib/runtime/runtime.unref call $~lib/runtime/runtime.unrefUnregistered
i32.const 2 i32.const 2
i32.store i32.store
local.get $0 local.get $0
@ -3023,10 +3015,10 @@
unreachable unreachable
end end
) )
(func $start (; 27 ;) (type $FUNCSIG$v) (func $start (; 26 ;) (type $FUNCSIG$v)
call $start:std/runtime call $start:std/runtime
) )
(func $null (; 28 ;) (type $FUNCSIG$v) (func $null (; 27 ;) (type $FUNCSIG$v)
nop nop
) )
) )

View File

@ -50,12 +50,12 @@ var ref2 = runtime.realloc(ref1, barrier2);
assert(ref1 != ref2); // moves assert(ref1 != ref2); // moves
var header2 = changetype<runtime.Header>(ref2 - runtime.Header.SIZE); var header2 = changetype<runtime.Header>(ref2 - runtime.Header.SIZE);
assert(header2.payloadSize == barrier2); assert(header2.payloadSize == barrier2);
runtime.free(ref2); runtime.freeUnregistered(ref2);
var ref3 = runtime.alloc(barrier2); var ref3 = runtime.alloc(barrier2);
assert(ref1 == ref3); // reuses space of ref1 (free'd in realloc), ref2 (explicitly free'd) assert(ref1 == ref3); // reuses space of ref1 (free'd in realloc), ref2 (explicitly free'd)
var ref4 = runtime.alloc(barrier1); var ref4 = runtime.alloc(barrier1);
runtime.register<A>(ref4); // should call __REGISTER_IMPL gc.register<A>(ref4); // should call __gc_register
assert(register_ref == ref4); assert(register_ref == ref4);
var header4 = changetype<runtime.Header>(register_ref - runtime.Header.SIZE); var header4 = changetype<runtime.Header>(register_ref - runtime.Header.SIZE);
assert(header4.classId == gc.classId<A>()); assert(header4.classId == gc.classId<A>());

View File

@ -1466,7 +1466,7 @@
call $~lib/allocator/tlsf/__memory_allocate call $~lib/allocator/tlsf/__memory_allocate
return return
) )
(func $~lib/runtime/runtime.allocRaw (; 24 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32) (func $~lib/runtime/runtime.alloc (; 24 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
(local $1 i32) (local $1 i32)
local.get $0 local.get $0
call $~lib/runtime/runtime.adjust call $~lib/runtime/runtime.adjust
@ -1488,278 +1488,7 @@
i32.const 16 i32.const 16
i32.add i32.add
) )
(func $~lib/util/memory/memset (; 25 ;) (type $FUNCSIG$viii) (param $0 i32) (param $1 i32) (param $2 i32) (func $~lib/util/memory/memcpy (; 25 ;) (type $FUNCSIG$viii) (param $0 i32) (param $1 i32) (param $2 i32)
(local $3 i32)
(local $4 i32)
(local $5 i64)
local.get $2
i32.eqz
if
return
end
local.get $0
local.get $1
i32.store8
local.get $0
local.get $2
i32.add
i32.const 1
i32.sub
local.get $1
i32.store8
local.get $2
i32.const 2
i32.le_u
if
return
end
local.get $0
i32.const 1
i32.add
local.get $1
i32.store8
local.get $0
i32.const 2
i32.add
local.get $1
i32.store8
local.get $0
local.get $2
i32.add
i32.const 2
i32.sub
local.get $1
i32.store8
local.get $0
local.get $2
i32.add
i32.const 3
i32.sub
local.get $1
i32.store8
local.get $2
i32.const 6
i32.le_u
if
return
end
local.get $0
i32.const 3
i32.add
local.get $1
i32.store8
local.get $0
local.get $2
i32.add
i32.const 4
i32.sub
local.get $1
i32.store8
local.get $2
i32.const 8
i32.le_u
if
return
end
i32.const 0
local.get $0
i32.sub
i32.const 3
i32.and
local.set $3
local.get $0
local.get $3
i32.add
local.set $0
local.get $2
local.get $3
i32.sub
local.set $2
local.get $2
i32.const -4
i32.and
local.set $2
i32.const -1
i32.const 255
i32.div_u
local.get $1
i32.const 255
i32.and
i32.mul
local.set $4
local.get $0
local.get $4
i32.store
local.get $0
local.get $2
i32.add
i32.const 4
i32.sub
local.get $4
i32.store
local.get $2
i32.const 8
i32.le_u
if
return
end
local.get $0
i32.const 4
i32.add
local.get $4
i32.store
local.get $0
i32.const 8
i32.add
local.get $4
i32.store
local.get $0
local.get $2
i32.add
i32.const 12
i32.sub
local.get $4
i32.store
local.get $0
local.get $2
i32.add
i32.const 8
i32.sub
local.get $4
i32.store
local.get $2
i32.const 24
i32.le_u
if
return
end
local.get $0
i32.const 12
i32.add
local.get $4
i32.store
local.get $0
i32.const 16
i32.add
local.get $4
i32.store
local.get $0
i32.const 20
i32.add
local.get $4
i32.store
local.get $0
i32.const 24
i32.add
local.get $4
i32.store
local.get $0
local.get $2
i32.add
i32.const 28
i32.sub
local.get $4
i32.store
local.get $0
local.get $2
i32.add
i32.const 24
i32.sub
local.get $4
i32.store
local.get $0
local.get $2
i32.add
i32.const 20
i32.sub
local.get $4
i32.store
local.get $0
local.get $2
i32.add
i32.const 16
i32.sub
local.get $4
i32.store
i32.const 24
local.get $0
i32.const 4
i32.and
i32.add
local.set $3
local.get $0
local.get $3
i32.add
local.set $0
local.get $2
local.get $3
i32.sub
local.set $2
local.get $4
i64.extend_i32_u
local.get $4
i64.extend_i32_u
i64.const 32
i64.shl
i64.or
local.set $5
block $break|0
loop $continue|0
local.get $2
i32.const 32
i32.ge_u
if
block
local.get $0
local.get $5
i64.store
local.get $0
i32.const 8
i32.add
local.get $5
i64.store
local.get $0
i32.const 16
i32.add
local.get $5
i64.store
local.get $0
i32.const 24
i32.add
local.get $5
i64.store
local.get $2
i32.const 32
i32.sub
local.set $2
local.get $0
i32.const 32
i32.add
local.set $0
end
br $continue|0
end
end
end
)
(func $~lib/memory/memory.fill (; 26 ;) (type $FUNCSIG$viii) (param $0 i32) (param $1 i32) (param $2 i32)
local.get $0
local.get $1
local.get $2
call $~lib/util/memory/memset
)
(func $~lib/runtime/runtime.alloc (; 27 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
(local $1 i32)
local.get $0
call $~lib/runtime/runtime.allocRaw
local.set $1
local.get $1
i32.const 0
local.get $0
call $~lib/memory/memory.fill
local.get $1
)
(func $~lib/util/memory/memcpy (; 28 ;) (type $FUNCSIG$viii) (param $0 i32) (param $1 i32) (param $2 i32)
(local $3 i32) (local $3 i32)
(local $4 i32) (local $4 i32)
(local $5 i32) (local $5 i32)
@ -2960,7 +2689,7 @@
i32.store8 i32.store8
end end
) )
(func $~lib/util/memory/memmove (; 29 ;) (type $FUNCSIG$viii) (param $0 i32) (param $1 i32) (param $2 i32) (func $~lib/util/memory/memmove (; 26 ;) (type $FUNCSIG$viii) (param $0 i32) (param $1 i32) (param $2 i32)
(local $3 i32) (local $3 i32)
local.get $0 local.get $0
local.get $1 local.get $1
@ -3187,13 +2916,273 @@
end end
end end
) )
(func $~lib/memory/memory.copy (; 30 ;) (type $FUNCSIG$viii) (param $0 i32) (param $1 i32) (param $2 i32) (func $~lib/memory/memory.copy (; 27 ;) (type $FUNCSIG$viii) (param $0 i32) (param $1 i32) (param $2 i32)
local.get $0 local.get $0
local.get $1 local.get $1
local.get $2 local.get $2
call $~lib/util/memory/memmove call $~lib/util/memory/memmove
) )
(func $~lib/allocator/tlsf/__memory_free (; 31 ;) (type $FUNCSIG$vi) (param $0 i32) (func $~lib/util/memory/memset (; 28 ;) (type $FUNCSIG$viii) (param $0 i32) (param $1 i32) (param $2 i32)
(local $3 i32)
(local $4 i32)
(local $5 i64)
local.get $2
i32.eqz
if
return
end
local.get $0
local.get $1
i32.store8
local.get $0
local.get $2
i32.add
i32.const 1
i32.sub
local.get $1
i32.store8
local.get $2
i32.const 2
i32.le_u
if
return
end
local.get $0
i32.const 1
i32.add
local.get $1
i32.store8
local.get $0
i32.const 2
i32.add
local.get $1
i32.store8
local.get $0
local.get $2
i32.add
i32.const 2
i32.sub
local.get $1
i32.store8
local.get $0
local.get $2
i32.add
i32.const 3
i32.sub
local.get $1
i32.store8
local.get $2
i32.const 6
i32.le_u
if
return
end
local.get $0
i32.const 3
i32.add
local.get $1
i32.store8
local.get $0
local.get $2
i32.add
i32.const 4
i32.sub
local.get $1
i32.store8
local.get $2
i32.const 8
i32.le_u
if
return
end
i32.const 0
local.get $0
i32.sub
i32.const 3
i32.and
local.set $3
local.get $0
local.get $3
i32.add
local.set $0
local.get $2
local.get $3
i32.sub
local.set $2
local.get $2
i32.const -4
i32.and
local.set $2
i32.const -1
i32.const 255
i32.div_u
local.get $1
i32.const 255
i32.and
i32.mul
local.set $4
local.get $0
local.get $4
i32.store
local.get $0
local.get $2
i32.add
i32.const 4
i32.sub
local.get $4
i32.store
local.get $2
i32.const 8
i32.le_u
if
return
end
local.get $0
i32.const 4
i32.add
local.get $4
i32.store
local.get $0
i32.const 8
i32.add
local.get $4
i32.store
local.get $0
local.get $2
i32.add
i32.const 12
i32.sub
local.get $4
i32.store
local.get $0
local.get $2
i32.add
i32.const 8
i32.sub
local.get $4
i32.store
local.get $2
i32.const 24
i32.le_u
if
return
end
local.get $0
i32.const 12
i32.add
local.get $4
i32.store
local.get $0
i32.const 16
i32.add
local.get $4
i32.store
local.get $0
i32.const 20
i32.add
local.get $4
i32.store
local.get $0
i32.const 24
i32.add
local.get $4
i32.store
local.get $0
local.get $2
i32.add
i32.const 28
i32.sub
local.get $4
i32.store
local.get $0
local.get $2
i32.add
i32.const 24
i32.sub
local.get $4
i32.store
local.get $0
local.get $2
i32.add
i32.const 20
i32.sub
local.get $4
i32.store
local.get $0
local.get $2
i32.add
i32.const 16
i32.sub
local.get $4
i32.store
i32.const 24
local.get $0
i32.const 4
i32.and
i32.add
local.set $3
local.get $0
local.get $3
i32.add
local.set $0
local.get $2
local.get $3
i32.sub
local.set $2
local.get $4
i64.extend_i32_u
local.get $4
i64.extend_i32_u
i64.const 32
i64.shl
i64.or
local.set $5
block $break|0
loop $continue|0
local.get $2
i32.const 32
i32.ge_u
if
block
local.get $0
local.get $5
i64.store
local.get $0
i32.const 8
i32.add
local.get $5
i64.store
local.get $0
i32.const 16
i32.add
local.get $5
i64.store
local.get $0
i32.const 24
i32.add
local.get $5
i64.store
local.get $2
i32.const 32
i32.sub
local.set $2
local.get $0
i32.const 32
i32.add
local.set $0
end
br $continue|0
end
end
end
)
(func $~lib/memory/memory.fill (; 29 ;) (type $FUNCSIG$viii) (param $0 i32) (param $1 i32) (param $2 i32)
local.get $0
local.get $1
local.get $2
call $~lib/util/memory/memset
)
(func $~lib/allocator/tlsf/__memory_free (; 30 ;) (type $FUNCSIG$vi) (param $0 i32)
(local $1 i32) (local $1 i32)
(local $2 i32) (local $2 i32)
(local $3 i32) (local $3 i32)
@ -3236,19 +3225,15 @@
end end
end end
) )
(func $~lib/memory/memory.free (; 32 ;) (type $FUNCSIG$vi) (param $0 i32) (func $~lib/memory/memory.free (; 31 ;) (type $FUNCSIG$vi) (param $0 i32)
local.get $0 local.get $0
call $~lib/allocator/tlsf/__memory_free call $~lib/allocator/tlsf/__memory_free
) )
(func $std/runtime/__gc_register (; 33 ;) (type $FUNCSIG$vi) (param $0 i32) (func $std/runtime/__gc_register (; 32 ;) (type $FUNCSIG$vi) (param $0 i32)
local.get $0 local.get $0
global.set $std/runtime/register_ref global.set $std/runtime/register_ref
) )
(func $~lib/gc/gc.register (; 34 ;) (type $FUNCSIG$vi) (param $0 i32) (func $~lib/runtime/runtime.realloc (; 33 ;) (type $FUNCSIG$iii) (param $0 i32) (param $1 i32) (result i32)
local.get $0
call $std/runtime/__gc_register
)
(func $~lib/runtime/runtime.realloc (; 35 ;) (type $FUNCSIG$iii) (param $0 i32) (param $1 i32) (result i32)
(local $2 i32) (local $2 i32)
(local $3 i32) (local $3 i32)
(local $4 i32) (local $4 i32)
@ -3282,7 +3267,8 @@
call $~lib/memory/memory.allocate call $~lib/memory/memory.allocate
local.set $5 local.set $5
local.get $5 local.get $5
i32.const -1520547049 local.get $2
i32.load
i32.store i32.store
local.get $5 local.get $5
i32.const 0 i32.const 0
@ -3318,7 +3304,7 @@
if if
i32.const 0 i32.const 0
i32.const 184 i32.const 184
i32.const 96 i32.const 87
i32.const 10 i32.const 10
call $~lib/env/abort call $~lib/env/abort
unreachable unreachable
@ -3327,7 +3313,7 @@
call $~lib/memory/memory.free call $~lib/memory/memory.free
else else
local.get $0 local.get $0
call $~lib/gc/gc.register call $std/runtime/__gc_register
end end
local.get $5 local.get $5
local.set $2 local.set $2
@ -3351,7 +3337,7 @@
i32.store offset=4 i32.store offset=4
local.get $0 local.get $0
) )
(func $~lib/runtime/runtime.unref (; 36 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32) (func $~lib/runtime/runtime.unrefUnregistered (; 34 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
(local $1 i32) (local $1 i32)
local.get $0 local.get $0
global.get $~lib/memory/HEAP_BASE global.get $~lib/memory/HEAP_BASE
@ -3362,7 +3348,7 @@
if if
i32.const 0 i32.const 0
i32.const 184 i32.const 184
i32.const 117 i32.const 111
i32.const 4 i32.const 4
call $~lib/env/abort call $~lib/env/abort
unreachable unreachable
@ -3379,25 +3365,25 @@
if if
i32.const 0 i32.const 0
i32.const 184 i32.const 184
i32.const 119 i32.const 113
i32.const 4 i32.const 4
call $~lib/env/abort call $~lib/env/abort
unreachable unreachable
end end
local.get $1 local.get $1
) )
(func $~lib/runtime/runtime.free<usize> (; 37 ;) (type $FUNCSIG$vi) (param $0 i32) (func $~lib/runtime/runtime.freeUnregistered<usize> (; 35 ;) (type $FUNCSIG$vi) (param $0 i32)
local.get $0 local.get $0
call $~lib/runtime/runtime.unref call $~lib/runtime/runtime.unrefUnregistered
call $~lib/memory/memory.free call $~lib/memory/memory.free
) )
(func $~lib/arraybuffer/ArrayBuffer#get:byteLength (; 38 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32) (func $~lib/arraybuffer/ArrayBuffer#get:byteLength (; 36 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
local.get $0 local.get $0
i32.const 16 i32.const 16
i32.sub i32.sub
i32.load offset=4 i32.load offset=4
) )
(func $~lib/string/String#get:length (; 39 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32) (func $~lib/string/String#get:length (; 37 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
local.get $0 local.get $0
i32.const 16 i32.const 16
i32.sub i32.sub
@ -3405,7 +3391,7 @@
i32.const 1 i32.const 1
i32.shr_u i32.shr_u
) )
(func $start:std/runtime (; 40 ;) (type $FUNCSIG$v) (func $start:std/runtime (; 38 ;) (type $FUNCSIG$v)
(local $0 i32) (local $0 i32)
call $start:~lib/allocator/tlsf call $start:~lib/allocator/tlsf
i32.const 2 i32.const 2
@ -3631,7 +3617,7 @@
unreachable unreachable
end end
global.get $std/runtime/ref2 global.get $std/runtime/ref2
call $~lib/runtime/runtime.free<usize> call $~lib/runtime/runtime.freeUnregistered<usize>
global.get $std/runtime/barrier2 global.get $std/runtime/barrier2
call $~lib/runtime/runtime.alloc call $~lib/runtime/runtime.alloc
global.set $std/runtime/ref3 global.set $std/runtime/ref3
@ -3650,15 +3636,15 @@
global.get $std/runtime/barrier1 global.get $std/runtime/barrier1
call $~lib/runtime/runtime.alloc call $~lib/runtime/runtime.alloc
global.set $std/runtime/ref4 global.set $std/runtime/ref4
block $~lib/runtime/runtime.register<A>|inlined.0 (result i32) block $~lib/gc/gc.register<A>|inlined.0 (result i32)
global.get $std/runtime/ref4 global.get $std/runtime/ref4
local.set $0 local.set $0
local.get $0 local.get $0
call $~lib/runtime/runtime.unref call $~lib/runtime/runtime.unrefUnregistered
i32.const 2 i32.const 2
i32.store i32.store
local.get $0 local.get $0
call $~lib/gc/gc.register call $std/runtime/__gc_register
local.get $0 local.get $0
end end
drop drop
@ -3734,9 +3720,9 @@
unreachable unreachable
end end
) )
(func $start (; 41 ;) (type $FUNCSIG$v) (func $start (; 39 ;) (type $FUNCSIG$v)
call $start:std/runtime call $start:std/runtime
) )
(func $null (; 42 ;) (type $FUNCSIG$v) (func $null (; 40 ;) (type $FUNCSIG$v)
) )
) )