mirror of
https://github.com/Instadapp/Swap-Aggregator-Subgraph.git
synced 2024-07-29 21:57:12 +00:00
134 lines
4.0 KiB
TypeScript
134 lines
4.0 KiB
TypeScript
import { AL_MASK, OBJECT, OBJECT_OVERHEAD, BLOCK_MAXSIZE, BLOCK_OVERHEAD, BLOCK, OBJECT_MAXSIZE } from "./common";
|
|
import { E_ALLOCATION_TOO_LARGE } from "../util/error";
|
|
|
|
// === A minimal runtime stub ===
|
|
|
|
// @ts-ignore: decorator
|
|
@lazy var startOffset: usize = ((__heap_base + BLOCK_OVERHEAD + AL_MASK) & ~AL_MASK) - BLOCK_OVERHEAD;
|
|
// @ts-ignore: decorator
|
|
@lazy var offset: usize = startOffset;
|
|
|
|
function maybeGrowMemory(newOffset: usize): void {
|
|
// assumes newOffset is aligned
|
|
var pagesBefore = memory.size();
|
|
var maxOffset = ((<usize>pagesBefore << 16) + AL_MASK) & ~AL_MASK;
|
|
if (newOffset > maxOffset) {
|
|
let pagesNeeded = <i32>(((newOffset - maxOffset + 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 = newOffset;
|
|
}
|
|
|
|
// @ts-ignore: decorator
|
|
@inline function computeSize(size: usize): usize {
|
|
return ((size + BLOCK_OVERHEAD + AL_MASK) & ~AL_MASK) - BLOCK_OVERHEAD;
|
|
}
|
|
|
|
// @ts-ignore: decorator
|
|
@unsafe @global
|
|
export function __alloc(size: usize): usize {
|
|
if (size > BLOCK_MAXSIZE) throw new Error(E_ALLOCATION_TOO_LARGE);
|
|
var block = changetype<BLOCK>(offset);
|
|
var ptr = offset + BLOCK_OVERHEAD;
|
|
var payloadSize = computeSize(size);
|
|
maybeGrowMemory(ptr + payloadSize);
|
|
block.mmInfo = payloadSize;
|
|
return ptr;
|
|
}
|
|
|
|
// @ts-ignore: decorator
|
|
@unsafe @global
|
|
export function __realloc(ptr: usize, size: usize): usize {
|
|
assert(ptr != 0 && !(ptr & AL_MASK)); // must exist and be aligned
|
|
var block = changetype<BLOCK>(ptr - BLOCK_OVERHEAD);
|
|
var actualSize = block.mmInfo;
|
|
var isLast = ptr + actualSize == offset;
|
|
var payloadSize = computeSize(size);
|
|
if (size > actualSize) {
|
|
if (isLast) { // last block: grow
|
|
if (size > BLOCK_MAXSIZE) throw new Error(E_ALLOCATION_TOO_LARGE);
|
|
maybeGrowMemory(ptr + payloadSize);
|
|
block.mmInfo = payloadSize;
|
|
} else { // copy to new block at least double the size
|
|
let newPtr = __alloc(max<usize>(payloadSize, actualSize << 1));
|
|
memory.copy(newPtr, ptr, actualSize);
|
|
block = changetype<BLOCK>((ptr = newPtr) - BLOCK_OVERHEAD);
|
|
}
|
|
} else if (isLast) { // last block: shrink
|
|
offset = ptr + payloadSize;
|
|
block.mmInfo = payloadSize;
|
|
}
|
|
return ptr;
|
|
}
|
|
|
|
// @ts-ignore: decorator
|
|
@unsafe @global
|
|
export function __free(ptr: usize): void {
|
|
assert(ptr != 0 && !(ptr & AL_MASK)); // must exist and be aligned
|
|
var block = changetype<BLOCK>(ptr - BLOCK_OVERHEAD);
|
|
if (ptr + block.mmInfo == offset) { // last block: discard
|
|
offset = changetype<usize>(block);
|
|
}
|
|
}
|
|
|
|
// @ts-ignore: decorator
|
|
@unsafe @global
|
|
export function __reset(): void { // special
|
|
offset = startOffset;
|
|
}
|
|
|
|
// @ts-ignore: decorator
|
|
@unsafe @global
|
|
export function __new(size: usize, id: u32): usize {
|
|
if (size > OBJECT_MAXSIZE) throw new Error(E_ALLOCATION_TOO_LARGE);
|
|
var ptr = __alloc(OBJECT_OVERHEAD + size);
|
|
var object = changetype<OBJECT>(ptr - BLOCK_OVERHEAD);
|
|
object.gcInfo = 0;
|
|
object.gcInfo2 = 0;
|
|
object.rtId = id;
|
|
object.rtSize = <u32>size;
|
|
return ptr + OBJECT_OVERHEAD;
|
|
}
|
|
|
|
// @ts-ignore: decorator
|
|
@unsafe @global
|
|
export function __renew(oldPtr: usize, size: usize): usize {
|
|
if (size > OBJECT_MAXSIZE) throw new Error(E_ALLOCATION_TOO_LARGE);
|
|
var newPtr = __realloc(oldPtr - OBJECT_OVERHEAD, OBJECT_OVERHEAD + size);
|
|
changetype<OBJECT>(newPtr - BLOCK_OVERHEAD).rtSize = <u32>size;
|
|
return newPtr + OBJECT_OVERHEAD;
|
|
}
|
|
|
|
// @ts-ignore: decorator
|
|
@global @unsafe
|
|
export function __link(parentPtr: usize, childPtr: usize, expectMultiple: bool): void {
|
|
// nop
|
|
}
|
|
|
|
// @ts-ignore: decorator
|
|
@global @unsafe
|
|
export function __pin(ptr: usize): usize {
|
|
return ptr;
|
|
}
|
|
|
|
// @ts-ignore: decorator
|
|
@global @unsafe
|
|
export function __unpin(ptr: usize): void {
|
|
// nop
|
|
}
|
|
|
|
// @ts-ignore: decorator
|
|
@global @unsafe
|
|
function __visit(ptr: usize, cookie: u32): void { // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
// nop
|
|
}
|
|
|
|
// @ts-ignore: decorator
|
|
@global @unsafe
|
|
export function __collect(): void {
|
|
// nop
|
|
}
|