Skip to content

Commit 03bb15e

Browse files
authored
Fix some TLSF inconsistencies (#1061)
1 parent cd22a47 commit 03bb15e

Some content is hidden

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

54 files changed

+5851
-6026
lines changed

std/assembly/array.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ function ensureSize(array: usize, minSize: usize, alignLog2: u32): void {
1414
if (minSize > BLOCK_MAXSIZE >>> alignLog2) throw new RangeError(E_INVALIDLENGTH);
1515
let oldData = changetype<usize>(changetype<ArrayBufferView>(array).buffer);
1616
let newCapacity = minSize << alignLog2;
17-
let newData = __realloc(oldData, newCapacity);
17+
let newData = __realloc(oldData, newCapacity); // keeps RC
1818
memory.fill(newData + oldCapacity, 0, newCapacity - oldCapacity);
1919
if (newData !== oldData) { // oldData has been free'd
20-
store<usize>(array, __retain(newData), offsetof<ArrayBufferView>("buffer"));
20+
store<usize>(array, newData, offsetof<ArrayBufferView>("buffer"));
2121
store<usize>(array, newData, offsetof<ArrayBufferView>("dataStart"));
2222
}
2323
store<u32>(array, newCapacity, offsetof<ArrayBufferView>("byteLength"));

std/assembly/rt/tlsf.ts

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -486,7 +486,7 @@ export function maybeInitialize(): Root {
486486
var collectLock: bool = false;
487487

488488
/** Allocates a block of the specified size. */
489-
export function allocateBlock(root: Root, size: usize): Block {
489+
export function allocateBlock(root: Root, size: usize, id: u32): Block {
490490
if (DEBUG) assert(!collectLock); // must not allocate while collecting
491491
var payloadSize = prepareSize(size);
492492
var block = searchBlock(root, payloadSize);
@@ -509,7 +509,7 @@ export function allocateBlock(root: Root, size: usize): Block {
509509
}
510510
if (DEBUG) assert((block.mmInfo & ~TAGS_MASK) >= payloadSize); // must fit
511511
block.gcInfo = 0; // RC=0
512-
// block.rtId = 0; // set by the caller (__alloc)
512+
block.rtId = id;
513513
block.rtSize = size;
514514
removeBlock(root, <Block>block);
515515
prepareBlock(root, <Block>block, payloadSize);
@@ -521,12 +521,6 @@ export function allocateBlock(root: Root, size: usize): Block {
521521
export function reallocateBlock(root: Root, block: Block, size: usize): Block {
522522
var payloadSize = prepareSize(size);
523523
var blockInfo = block.mmInfo;
524-
if (DEBUG) {
525-
assert(
526-
!(blockInfo & FREE) && // must be used
527-
!(block.gcInfo & ~REFCOUNT_MASK) // not buffered or != BLACK
528-
);
529-
}
530524

531525
// possibly split and update runtime size if it still fits
532526
if (payloadSize <= (blockInfo & ~TAGS_MASK)) {
@@ -552,8 +546,8 @@ export function reallocateBlock(root: Root, block: Block, size: usize): Block {
552546
}
553547

554548
// otherwise move the block
555-
var newBlock = allocateBlock(root, size); // may invalidate cached blockInfo
556-
newBlock.rtId = block.rtId;
549+
var newBlock = allocateBlock(root, size, block.rtId); // may invalidate cached blockInfo
550+
newBlock.gcInfo = block.gcInfo; // keep RC
557551
memory.copy(changetype<usize>(newBlock) + BLOCK_OVERHEAD, changetype<usize>(block) + BLOCK_OVERHEAD, size);
558552
if (changetype<usize>(block) >= __heap_base) freeBlock(root, block);
559553
return newBlock;
@@ -562,30 +556,40 @@ export function reallocateBlock(root: Root, block: Block, size: usize): Block {
562556
/** Frees a block. */
563557
export function freeBlock(root: Root, block: Block): void {
564558
var blockInfo = block.mmInfo;
565-
assert(!(blockInfo & FREE)); // must be used (user might call through to this)
566559
block.mmInfo = blockInfo | FREE;
567560
insertBlock(root, block);
568561
if (isDefined(ASC_RTRACE)) onfree(block);
569562
}
570563

564+
/** Checks that a used block is valid to be freed or reallocated. */
565+
function checkUsedBlock(ref: usize): Block {
566+
var block = changetype<Block>(ref - BLOCK_OVERHEAD);
567+
assert(
568+
ref != 0 && !(ref & AL_MASK) && // must exist and be aligned
569+
!(block.mmInfo & FREE) && // must be used
570+
!(block.gcInfo & ~REFCOUNT_MASK) // not buffered or != BLACK
571+
);
572+
return block;
573+
}
574+
571575
// @ts-ignore: decorator
572576
@global @unsafe
573577
export function __alloc(size: usize, id: u32): usize {
574-
var block = allocateBlock(maybeInitialize(), size);
575-
block.rtId = id;
576-
return changetype<usize>(block) + BLOCK_OVERHEAD;
578+
return changetype<usize>(
579+
allocateBlock(maybeInitialize(), size, id)
580+
) + BLOCK_OVERHEAD;
577581
}
578582

579583
// @ts-ignore: decorator
580584
@global @unsafe
581585
export function __realloc(ref: usize, size: usize): usize {
582-
assert(ref != 0 && !(ref & AL_MASK)); // must exist and be aligned
583-
return changetype<usize>(reallocateBlock(maybeInitialize(), changetype<Block>(ref - BLOCK_OVERHEAD), size)) + BLOCK_OVERHEAD;
586+
return changetype<usize>(
587+
reallocateBlock(maybeInitialize(), checkUsedBlock(ref), size)
588+
) + BLOCK_OVERHEAD;
584589
}
585590

586591
// @ts-ignore: decorator
587592
@global @unsafe
588593
export function __free(ref: usize): void {
589-
assert(ref != 0 && !(ref & AL_MASK)); // must exist and be aligned
590-
freeBlock(maybeInitialize(), changetype<Block>(ref - BLOCK_OVERHEAD));
594+
freeBlock(maybeInitialize(), checkUsedBlock(ref));
591595
}

tests/allocators/rt-full/optimized.wat

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33
(type $i32_i32_=>_none (func (param i32 i32)))
44
(type $i32_i32_i32_=>_none (func (param i32 i32 i32)))
55
(type $i32_=>_i32 (func (param i32) (result i32)))
6-
(type $i32_i32_=>_i32 (func (param i32 i32) (result i32)))
76
(type $none_=>_none (func))
7+
(type $i32_i32_=>_i32 (func (param i32 i32) (result i32)))
88
(type $i32_i32_i32_i32_=>_none (func (param i32 i32 i32 i32)))
99
(type $none_=>_i32 (func (result i32)))
10+
(type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32)))
1011
(import "env" "abort" (func $~lib/builtins/abort (param i32 i32 i32 i32)))
1112
(memory $0 1)
1213
(data (i32.const 16) "(\00\00\00\01\00\00\00\01\00\00\00(\00\00\00a\00l\00l\00o\00c\00a\00t\00i\00o\00n\00 \00t\00o\00o\00 \00l\00a\00r\00g\00e")
@@ -976,15 +977,15 @@
976977
i32.store
977978
end
978979
)
979-
(func $~lib/rt/tlsf/allocateBlock (; 15 ;) (param $0 i32) (param $1 i32) (result i32)
980-
(local $2 i32)
980+
(func $~lib/rt/tlsf/allocateBlock (; 15 ;) (param $0 i32) (param $1 i32) (param $2 i32) (result i32)
981981
(local $3 i32)
982+
(local $4 i32)
982983
local.get $0
983984
local.get $1
984985
call $~lib/rt/tlsf/prepareSize
985-
local.tee $3
986+
local.tee $4
986987
call $~lib/rt/tlsf/searchBlock
987-
local.tee $2
988+
local.tee $3
988989
i32.eqz
989990
if
990991
i32.const 1
@@ -993,43 +994,43 @@
993994
i32.const 0
994995
global.set $~lib/rt/tlsf/collectLock
995996
local.get $0
996-
local.get $3
997+
local.get $4
997998
call $~lib/rt/tlsf/searchBlock
998-
local.tee $2
999+
local.tee $3
9991000
i32.eqz
10001001
if
10011002
local.get $0
1002-
local.get $3
1003+
local.get $4
10031004
call $~lib/rt/tlsf/growMemory
10041005
local.get $0
1005-
local.get $3
1006+
local.get $4
10061007
call $~lib/rt/tlsf/searchBlock
1007-
local.set $2
1008+
local.set $3
10081009
end
10091010
end
1010-
local.get $2
1011+
local.get $3
10111012
i32.const 0
10121013
i32.store offset=4
1014+
local.get $3
10131015
local.get $2
1016+
i32.store offset=8
1017+
local.get $3
10141018
local.get $1
10151019
i32.store offset=12
10161020
local.get $0
1017-
local.get $2
1021+
local.get $3
10181022
call $~lib/rt/tlsf/removeBlock
10191023
local.get $0
1020-
local.get $2
10211024
local.get $3
1025+
local.get $4
10221026
call $~lib/rt/tlsf/prepareBlock
1023-
local.get $2
1027+
local.get $3
10241028
)
10251029
(func $~lib/rt/tlsf/__alloc (; 16 ;) (param $0 i32) (param $1 i32) (result i32)
10261030
call $~lib/rt/tlsf/maybeInitialize
10271031
local.get $0
1028-
call $~lib/rt/tlsf/allocateBlock
1029-
local.tee $0
10301032
local.get $1
1031-
i32.store offset=8
1032-
local.get $0
1033+
call $~lib/rt/tlsf/allocateBlock
10331034
i32.const 16
10341035
i32.add
10351036
)

0 commit comments

Comments
 (0)