Skip to content

Commit 3988dd9

Browse files
committed
feat: enhance lowMemoryLimit to support larger than 64k memory limitation
1 parent 3defefd commit 3988dd9

File tree

192 files changed

+17464
-7134
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

192 files changed

+17464
-7134
lines changed

cli/options.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,7 @@
260260
},
261261
"lowMemoryLimit": {
262262
"category": "Features",
263-
"description": "Enforces very low (<64k) memory constraints.",
263+
"description": "Enforces memory constraints.",
264264
"default": 0,
265265
"type": "i"
266266
},

src/compiler.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ export class Options {
276276
noUnsafe: bool = false;
277277
/** If true, enables pedantic diagnostics. */
278278
pedantic: bool = false;
279-
/** Indicates a very low (<64k) memory limit. */
279+
/** Indicates a memory limit. */
280280
lowMemoryLimit: u32 = 0;
281281
/** If true, exports the runtime helpers. */
282282
exportRuntime: bool = false;
@@ -821,7 +821,7 @@ export class Compiler extends DiagnosticEmitter {
821821
// check that we didn't exceed lowMemoryLimit already
822822
let lowMemoryLimit32 = options.lowMemoryLimit;
823823
if (lowMemoryLimit32) {
824-
let lowMemoryLimit = i64_new(lowMemoryLimit32 & ~15);
824+
let lowMemoryLimit = i64_new(lowMemoryLimit32);
825825
if (i64_gt(memoryOffset, lowMemoryLimit)) {
826826
this.error(
827827
DiagnosticCode.Low_memory_limit_exceeded_by_static_data_0_1,

std/assembly/rt/tlsf.ts

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,11 @@ import { E_ALLOCATION_TOO_LARGE } from "../util/error";
196196
);
197197
}
198198

199+
// @ts-ignore: decorator
200+
@inline function sizeRoundToPage(size: usize): i32 {
201+
return <i32>((size + 0xffff) >>> 16);
202+
}
203+
199204
/** Inserts a previously used block back into the free list. */
200205
function insertBlock(root: Root, block: Block): void {
201206
if (DEBUG) assert(block); // cannot be null
@@ -427,10 +432,6 @@ function addMemory(root: Root, start: usize, endU64: u64): bool {
427432

428433
/** Grows memory to fit at least another block of the specified size. */
429434
function growMemory(root: Root, size: usize): void {
430-
if (ASC_LOW_MEMORY_LIMIT) {
431-
unreachable();
432-
return;
433-
}
434435
// Here, both rounding performed in searchBlock ...
435436
if (size >= SB_SIZE) {
436437
size = roundSize(size);
@@ -439,13 +440,23 @@ function growMemory(root: Root, size: usize): void {
439440
// to merge with the tail block, that's one time, otherwise it's two times.
440441
let pagesBefore = memory.size();
441442
size += BLOCK_OVERHEAD << usize((<usize>pagesBefore << 16) - BLOCK_OVERHEAD != changetype<usize>(GETTAIL(root)));
442-
let pagesNeeded = <i32>(((size + 0xffff) & ~0xffff) >>> 16);
443+
if (ASC_LOW_MEMORY_LIMIT) {
444+
if ((<usize>pagesBefore << 16) + size > <usize>ASC_LOW_MEMORY_LIMIT) unreachable();
445+
}
446+
let pagesNeeded = sizeRoundToPage(size);
443447
let pagesWanted = max(pagesBefore, pagesNeeded); // double memory
448+
if (ASC_LOW_MEMORY_LIMIT) {
449+
pagesWanted = min(pagesWanted, sizeRoundToPage(ASC_LOW_MEMORY_LIMIT) - pagesBefore);
450+
}
444451
if (memory.grow(pagesWanted) < 0) {
445452
if (memory.grow(pagesNeeded) < 0) unreachable();
446453
}
447454
let pagesAfter = memory.size();
448-
addMemory(root, <usize>pagesBefore << 16, <u64>pagesAfter << 16);
455+
if (ASC_LOW_MEMORY_LIMIT) {
456+
addMemory(root, <usize>pagesBefore << 16, min(<u64>pagesAfter << 16, <u64>ASC_LOW_MEMORY_LIMIT & ~AL_MASK));
457+
} else {
458+
addMemory(root, <usize>pagesBefore << 16, <u64>pagesAfter << 16);
459+
}
449460
}
450461

451462
/** Computes the size (excl. header) of a block. */
@@ -467,7 +478,7 @@ function initialize(): void {
467478
if (isDefined(ASC_RTRACE)) oninit(__heap_base);
468479
let rootOffset = (__heap_base + AL_MASK) & ~AL_MASK;
469480
let pagesBefore = memory.size();
470-
let pagesNeeded = <i32>((((rootOffset + ROOT_SIZE) + 0xffff) & ~0xffff) >>> 16);
481+
let pagesNeeded = sizeRoundToPage(rootOffset + ROOT_SIZE);
471482
if (pagesNeeded > pagesBefore && memory.grow(pagesNeeded - pagesBefore) < 0) unreachable();
472483
let root = changetype<Root>(rootOffset);
473484
root.flMap = 0;
@@ -480,9 +491,9 @@ function initialize(): void {
480491
}
481492
let memStart = rootOffset + ROOT_SIZE;
482493
if (ASC_LOW_MEMORY_LIMIT) {
483-
const memEnd = <u64>ASC_LOW_MEMORY_LIMIT & ~AL_MASK;
484-
if (memStart <= memEnd) addMemory(root, memStart, memEnd);
485-
else unreachable(); // low memory limit already exceeded
494+
const limitedEnd: u64 = min(<u64>memory.size() << 16, <u64>ASC_LOW_MEMORY_LIMIT & ~AL_MASK);
495+
if (<u64>memStart > limitedEnd) unreachable(); // low memory limit already exceeded
496+
addMemory(root, memStart, limitedEnd);
486497
} else {
487498
addMemory(root, memStart, <u64>memory.size() << 16);
488499
}

tests/compiler.js

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -380,14 +380,13 @@ async function runTest(basename) {
380380
if (config.skipInstantiate) {
381381
instantiateDebug.end(SKIPPED);
382382
} else {
383-
384-
if (!await testInstantiate(debugBuffer, glue, stderr)) {
383+
if (!await testInstantiate(debugBuffer, glue, stderr, !!config.expectedFailed)) {
385384
instantiateDebug.end(FAILURE);
386385
return prepareResult(FAILURE, "instantiate error (debug)");
387386
}
388387
instantiateDebug.end(SUCCESS);
389388
const instantiateRelease = section("instantiate release");
390-
if (!await testInstantiate(releaseBuffer, glue, stderr)) {
389+
if (!await testInstantiate(releaseBuffer, glue, stderr, !!config.expectedFailed)) {
391390
instantiateRelease.end(FAILURE);
392391
return prepareResult(FAILURE, "instantiate error (release)");
393392
}
@@ -423,7 +422,7 @@ async function runTest(basename) {
423422

424423
const rtracedBuffer = stdout.toBuffer();
425424
const instantiateRtrace = section("instantiate rtrace");
426-
if (!await testInstantiate(rtracedBuffer, glue, stderr)) {
425+
if (!await testInstantiate(rtracedBuffer, glue, stderr, !!config.expectedFailed)) {
427426
instantiateRtrace.end(FAILURE);
428427
return prepareResult(FAILURE, "rtrace error");
429428
}
@@ -434,7 +433,7 @@ async function runTest(basename) {
434433
}
435434

436435
// Tests if instantiation of a module succeeds
437-
async function testInstantiate(binaryBuffer, glue, stderr) {
436+
async function testInstantiate(binaryBuffer, glue, stderr, expectedFailed) {
438437
let failed = false;
439438
try {
440439
const memory = new WebAssembly.Memory({ initial: 10 });
@@ -539,23 +538,21 @@ async function testInstantiate(binaryBuffer, glue, stderr) {
539538
failed = true;
540539
console.log(` memory leak detected: ${leakCount} leaking`);
541540
}
542-
if (!failed) {
543-
if (rtrace.active) {
544-
console.log(" " +
545-
rtrace.allocCount + " allocs, " +
546-
rtrace.freeCount + " frees, " +
547-
rtrace.resizeCount + " resizes, " +
548-
rtrace.moveCount + " moves"
549-
);
550-
}
551-
return true;
541+
if (rtrace.active) {
542+
console.log(" " +
543+
rtrace.allocCount + " allocs, " +
544+
rtrace.freeCount + " frees, " +
545+
rtrace.resizeCount + " resizes, " +
546+
rtrace.moveCount + " moves"
547+
);
552548
}
553549
} catch (err) {
550+
failed = true;
554551
stderr.write("---\n");
555552
stderr.write(err.stack);
556553
stderr.write("\n---\n");
557554
}
558-
return false;
555+
return failed == expectedFailed;
559556
}
560557

561558
// Evaluates the overall test result

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy