diff --git a/std/assembly/rt/README.md b/std/assembly/rt/README.md index 1fb78f57..6e501d92 100644 --- a/std/assembly/rt/README.md +++ b/std/assembly/rt/README.md @@ -12,6 +12,9 @@ Interface Dynamically allocates a chunk of memory of at least the specified size and returns its address. Alignment is guaranteed to be 16 bytes to fit up to v128 values naturally. +* **__rt_reallocate**(ref: `usize`, size: `usize`): `usize`
+ Dynamically changes the size of a chunk of memory, possibly moving it to a new address. + * **__rt_free**(ref: `usize`): `void`
Frees a dynamically allocated chunk of memory by its address. diff --git a/std/assembly/rt/stub.ts b/std/assembly/rt/stub.ts index da02be77..386a202d 100644 --- a/std/assembly/rt/stub.ts +++ b/std/assembly/rt/stub.ts @@ -2,7 +2,7 @@ import { AL_MASK, CommonBlock } from "./common"; // @ts-ignore: decorator @inline -const BLOCK_OVERHEAD = offsetof(); +const BLOCK_OVERHEAD = (offsetof() + AL_MASK) & ~AL_MASK; // @ts-ignore: decorator @inline @@ -43,9 +43,15 @@ function __rt_allocate(size: usize, id: u32): usize { @unsafe @global function __rt_reallocate(ref: usize, size: usize): usize { var block = changetype(ref - BLOCK_OVERHEAD); - var newRef = __rt_allocate(size, block.rtId); - memory.copy(newRef, ref, block.rtSize); - return newRef; + var oldSize = block.rtSize; + if (size > oldSize) { + let newRef = __rt_allocate(size, block.rtId); + memory.copy(newRef, ref, oldSize); + ref = newRef; + } else { + block.rtSize = size; + } + return ref; } // @ts-ignore: decorator