Rework static memory segment creation; Fix stdlib gc hooks not marking own fields; Align everything to 8 bytes that might be touched by GC

This commit is contained in:
dcodeIO
2018-08-04 00:36:59 +02:00
parent 61de7cf962
commit 631478c7c9
61 changed files with 11944 additions and 5286 deletions

View File

@ -15,24 +15,21 @@ var offset: usize = startOffset;
// Memory allocator interface
@global export function __memory_allocate(size: usize): usize {
if (size) {
if (size > MAX_SIZE_32) unreachable();
let ptr = offset;
let newPtr = (ptr + size + AL_MASK) & ~AL_MASK;
let pagesBefore = memory.size();
if (newPtr > <usize>pagesBefore << 16) {
let pagesNeeded = ((newPtr - ptr + 0xffff) & ~0xffff) >>> 16;
let pagesWanted = max(pagesBefore, pagesNeeded); // double memory
if (memory.grow(pagesWanted) < 0) {
if (memory.grow(pagesNeeded) < 0) {
unreachable(); // out of memory
}
if (size > MAX_SIZE_32) unreachable();
var ptr = offset;
var newPtr = (ptr + max<usize>(size, 1) + AL_MASK) & ~AL_MASK;
var pagesBefore = memory.size();
if (newPtr > <usize>pagesBefore << 16) {
let pagesNeeded = ((newPtr - ptr + 0xffff) & ~0xffff) >>> 16;
let pagesWanted = max(pagesBefore, pagesNeeded); // double memory
if (memory.grow(pagesWanted) < 0) {
if (memory.grow(pagesNeeded) < 0) {
unreachable(); // out of memory
}
}
offset = newPtr;
return ptr;
}
return 0;
offset = newPtr;
return ptr;
}
@global export function __memory_free(ptr: usize): void { /* nop */ }

View File

@ -458,34 +458,30 @@ var ROOT: Root = changetype<Root>(0);
}
// search for a suitable block
var data: usize = 0;
if (size) {
if (size > Block.MAX_SIZE) unreachable();
// 32-bit MAX_SIZE is 1 << 30 and itself aligned, hence the following can't overflow MAX_SIZE
size = max<usize>((size + AL_MASK) & ~AL_MASK, Block.MIN_SIZE);
if (size > Block.MAX_SIZE) unreachable();
let block = root.search(size);
if (!block) {
// 32-bit MAX_SIZE is 1 << 30 and itself aligned, hence the following can't overflow MAX_SIZE
size = max<usize>((size + AL_MASK) & ~AL_MASK, Block.MIN_SIZE);
// request more memory
let pagesBefore = memory.size();
let pagesNeeded = <i32>(((size + 0xffff) & ~0xffff) >>> 16);
let pagesWanted = max(pagesBefore, pagesNeeded); // double memory
if (memory.grow(pagesWanted) < 0) {
if (memory.grow(pagesNeeded) < 0) {
unreachable(); // out of memory
}
var block = root.search(size);
if (!block) {
// request more memory
let pagesBefore = memory.size();
let pagesNeeded = <i32>(((size + 0xffff) & ~0xffff) >>> 16);
let pagesWanted = max(pagesBefore, pagesNeeded); // double memory
if (memory.grow(pagesWanted) < 0) {
if (memory.grow(pagesNeeded) < 0) {
unreachable(); // out of memory
}
let pagesAfter = memory.size();
root.addMemory(<usize>pagesBefore << 16, <usize>pagesAfter << 16);
block = assert(root.search(size)); // must be found now
}
assert((block.info & ~TAGS) >= size);
data = root.use(<Block>block, size);
let pagesAfter = memory.size();
root.addMemory(<usize>pagesBefore << 16, <usize>pagesAfter << 16);
block = assert(root.search(size)); // must be found now
}
return data;
assert((block.info & ~TAGS) >= size);
return root.use(<Block>block, size);
}
/** Frees the chunk of memory at the specified address. */

View File

@ -334,8 +334,9 @@ export class Array<T> {
}
private __gc(): void {
var buffer = this.buffer_;
__gc_mark(changetype<usize>(buffer)); // tslint:disable-line
if (isManaged<T>()) {
let buffer = this.buffer_;
let offset: usize = 0;
let end = <usize>this.length_ << alignof<usize>();
while (offset < end) {

View File

@ -153,6 +153,13 @@ function step(): void {
if (TRACE) trace("gc~step/MARK iterate", 1, objToRef(obj));
iter = obj;
obj.color = <i32>!white;
// if (TRACE) {
// trace(" next/prev/hook", 3,
// changetype<usize>(obj.next),
// changetype<usize>(obj.prev),
// changetype<u32>(obj.hookFn)
// );
// }
obj.hookFn(objToRef(obj));
} else {
if (TRACE) trace("gc~step/MARK finish");

View File

@ -166,8 +166,10 @@ export class Map<K,V> {
}
private __gc(): void {
__gc_mark(changetype<usize>(this.buckets)); // tslint:disable-line
var entries = this.entries;
__gc_mark(changetype<usize>(entries)); // tslint:disable-line
if (isManaged<K>() || isManaged<V>()) {
let entries = this.entries;
let offset: usize = 0;
let end: usize = this.entriesOffset * ENTRY_SIZE<K,V>();
while (offset < end) {

View File

@ -154,8 +154,10 @@ export class Set<K> {
}
private __gc(): void {
__gc_mark(changetype<usize>(this.buckets)); // tslint:disable-line
var entries = this.entries;
__gc_mark(changetype<usize>(entries)); // tslint:disable-line
if (isManaged<K>()) {
let entries = this.entries;
let offset: usize = 0;
let end: usize = this.entriesOffset * ENTRY_SIZE<K>();
while (offset < end) {