Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix some TLSF inconsistencies #1061

Merged
merged 2 commits into from
Jan 19, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions std/assembly/array.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ function ensureSize(array: usize, minSize: usize, alignLog2: u32): void {
if (minSize > BLOCK_MAXSIZE >>> alignLog2) throw new RangeError(E_INVALIDLENGTH);
let oldData = changetype<usize>(changetype<ArrayBufferView>(array).buffer);
let newCapacity = minSize << alignLog2;
let newData = __realloc(oldData, newCapacity);
let newData = __realloc(oldData, newCapacity); // keeps RC
memory.fill(newData + oldCapacity, 0, newCapacity - oldCapacity);
if (newData !== oldData) { // oldData has been free'd
store<usize>(array, __retain(newData), offsetof<ArrayBufferView>("buffer"));
store<usize>(array, newData, offsetof<ArrayBufferView>("buffer"));
store<usize>(array, newData, offsetof<ArrayBufferView>("dataStart"));
}
store<u32>(array, newCapacity, offsetof<ArrayBufferView>("byteLength"));
Expand Down
40 changes: 22 additions & 18 deletions std/assembly/rt/tlsf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -486,7 +486,7 @@ export function maybeInitialize(): Root {
var collectLock: bool = false;

/** Allocates a block of the specified size. */
export function allocateBlock(root: Root, size: usize): Block {
export function allocateBlock(root: Root, size: usize, id: u32): Block {
if (DEBUG) assert(!collectLock); // must not allocate while collecting
var payloadSize = prepareSize(size);
var block = searchBlock(root, payloadSize);
Expand All @@ -509,7 +509,7 @@ export function allocateBlock(root: Root, size: usize): Block {
}
if (DEBUG) assert((block.mmInfo & ~TAGS_MASK) >= payloadSize); // must fit
block.gcInfo = 0; // RC=0
// block.rtId = 0; // set by the caller (__alloc)
block.rtId = id;
block.rtSize = size;
removeBlock(root, <Block>block);
prepareBlock(root, <Block>block, payloadSize);
Expand All @@ -521,12 +521,6 @@ export function allocateBlock(root: Root, size: usize): Block {
export function reallocateBlock(root: Root, block: Block, size: usize): Block {
var payloadSize = prepareSize(size);
var blockInfo = block.mmInfo;
if (DEBUG) {
assert(
!(blockInfo & FREE) && // must be used
!(block.gcInfo & ~REFCOUNT_MASK) // not buffered or != BLACK
);
}

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

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

/** Checks that a used block is valid to be freed or reallocated. */
function checkUsedBlock(ref: usize): Block {
var block = changetype<Block>(ref - BLOCK_OVERHEAD);
assert(
ref != 0 && !(ref & AL_MASK) && // must exist and be aligned
!(block.mmInfo & FREE) && // must be used
!(block.gcInfo & ~REFCOUNT_MASK) // not buffered or != BLACK
);
return block;
}

// @ts-ignore: decorator
@global @unsafe
export function __alloc(size: usize, id: u32): usize {
var block = allocateBlock(maybeInitialize(), size);
block.rtId = id;
return changetype<usize>(block) + BLOCK_OVERHEAD;
return changetype<usize>(
allocateBlock(maybeInitialize(), size, id)
) + BLOCK_OVERHEAD;
}

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

// @ts-ignore: decorator
@global @unsafe
export function __free(ref: usize): void {
assert(ref != 0 && !(ref & AL_MASK)); // must exist and be aligned
freeBlock(maybeInitialize(), changetype<Block>(ref - BLOCK_OVERHEAD));
freeBlock(maybeInitialize(), checkUsedBlock(ref));
}
37 changes: 19 additions & 18 deletions tests/allocators/rt-full/optimized.wat
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
(type $i32_i32_=>_none (func (param i32 i32)))
(type $i32_i32_i32_=>_none (func (param i32 i32 i32)))
(type $i32_=>_i32 (func (param i32) (result i32)))
(type $i32_i32_=>_i32 (func (param i32 i32) (result i32)))
(type $none_=>_none (func))
(type $i32_i32_=>_i32 (func (param i32 i32) (result i32)))
(type $i32_i32_i32_i32_=>_none (func (param i32 i32 i32 i32)))
(type $none_=>_i32 (func (result i32)))
(type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32)))
(import "env" "abort" (func $~lib/builtins/abort (param i32 i32 i32 i32)))
(memory $0 1)
(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")
Expand Down Expand Up @@ -976,15 +977,15 @@
i32.store
end
)
(func $~lib/rt/tlsf/allocateBlock (; 15 ;) (param $0 i32) (param $1 i32) (result i32)
(local $2 i32)
(func $~lib/rt/tlsf/allocateBlock (; 15 ;) (param $0 i32) (param $1 i32) (param $2 i32) (result i32)
(local $3 i32)
(local $4 i32)
local.get $0
local.get $1
call $~lib/rt/tlsf/prepareSize
local.tee $3
local.tee $4
call $~lib/rt/tlsf/searchBlock
local.tee $2
local.tee $3
i32.eqz
if
i32.const 1
Expand All @@ -993,43 +994,43 @@
i32.const 0
global.set $~lib/rt/tlsf/collectLock
local.get $0
local.get $3
local.get $4
call $~lib/rt/tlsf/searchBlock
local.tee $2
local.tee $3
i32.eqz
if
local.get $0
local.get $3
local.get $4
call $~lib/rt/tlsf/growMemory
local.get $0
local.get $3
local.get $4
call $~lib/rt/tlsf/searchBlock
local.set $2
local.set $3
end
end
local.get $2
local.get $3
i32.const 0
i32.store offset=4
local.get $3
local.get $2
i32.store offset=8
local.get $3
local.get $1
i32.store offset=12
local.get $0
local.get $2
local.get $3
call $~lib/rt/tlsf/removeBlock
local.get $0
local.get $2
local.get $3
local.get $4
call $~lib/rt/tlsf/prepareBlock
local.get $2
local.get $3
)
(func $~lib/rt/tlsf/__alloc (; 16 ;) (param $0 i32) (param $1 i32) (result i32)
call $~lib/rt/tlsf/maybeInitialize
local.get $0
call $~lib/rt/tlsf/allocateBlock
local.tee $0
local.get $1
i32.store offset=8
local.get $0
call $~lib/rt/tlsf/allocateBlock
i32.const 16
i32.add
)
Expand Down
Loading