mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-06-12 06:21:29 +00:00
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:
@ -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 */ }
|
||||
|
@ -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. */
|
||||
|
@ -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) {
|
||||
|
@ -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");
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
Reference in New Issue
Block a user