Skip to content

Commit

Permalink
Fix invalid reference counts after internal realloc, see #672
Browse files Browse the repository at this point in the history
Previously realloc falsely copied the RC of the old block and missed to inform rtrace of the implicit free
  • Loading branch information
dcodeIO committed Jun 17, 2019
1 parent f48f3c9 commit 49edefc
Show file tree
Hide file tree
Showing 35 changed files with 794 additions and 747 deletions.
38 changes: 14 additions & 24 deletions src/builtins.ts
Expand Up @@ -4060,14 +4060,14 @@ export function compileVisitMembers(compiler: Compiler): void {
assert(id == lastId++);

let visitImpl: Element | null;
let code = new Array<ExpressionRef>();

// if a library element, check if it implements a custom traversal function
if (instance.isDeclaredInLibrary && (visitImpl = instance.lookupInSelf("__visit_impl"))) {
assert(visitImpl.kind == ElementKind.FUNCTION_PROTOTYPE);
let visitFunc = program.resolver.resolveFunction(<FunctionPrototype>visitImpl, null);
let block: RelooperBlockRef;
if (!visitFunc || !compiler.compileFunction(visitFunc)) {
block = relooper.addBlock(
code.push(
module.unreachable()
);
} else {
Expand All @@ -4078,26 +4078,16 @@ export function compileVisitMembers(compiler: Compiler): void {
visitSig.returnType == Type.void &&
visitSig.thisType == instance.type
);
let callExpr = module.call(visitFunc.internalName, [
module.local_get(0, nativeSizeType), // ref
module.local_get(1, NativeType.I32) // cookie
], NativeType.None);
block = relooper.addBlock(
instance.base
? callExpr // branch will be added later
: module.block(null, [
callExpr,
module.return()
])
code.push(
module.call(visitFunc.internalName, [
module.local_get(0, nativeSizeType), // ref
module.local_get(1, NativeType.I32) // cookie
], NativeType.None)
);
}
relooper.addBranchForSwitch(outer, block, [ id ]);
blocks.push(block);

// otherwise generate one
// otherwise generate traversal logic for own fields
} else {
// traverse references assigned to own fields
let code = new Array<ExpressionRef>();
let members = instance.members;
if (members) {
for (let member of members.values()) {
Expand Down Expand Up @@ -4127,13 +4117,13 @@ export function compileVisitMembers(compiler: Compiler): void {
}
}
}
if (!instance.base) code.push(module.return());
let block = relooper.addBlock(
flatten(module, code, NativeType.None)
);
relooper.addBranchForSwitch(outer, block, [ id ]);
blocks.push(block);
}
if (!instance.base) code.push(module.return());
let block = relooper.addBlock(
flatten(module, code, NativeType.None)
);
relooper.addBranchForSwitch(outer, block, [ id ]);
blocks.push(block);
}
for (let [id, instance] of managedClasses) {
let base = instance.base;
Expand Down
2 changes: 1 addition & 1 deletion std/assembly/rt/pure.ts
Expand Up @@ -23,7 +23,7 @@ import { onincrement, ondecrement, onfree, onalloc } from "./rtrace";
// @ts-ignore: decorator
@inline const COLOR_MASK: u32 = ((1 << COLOR_BITS) - 1) << COLOR_SHIFT;
// @ts-ignore: decorator
@inline const REFCOUNT_MASK: u32 = (1 << COLOR_SHIFT) - 1;
@inline export const REFCOUNT_MASK: u32 = (1 << COLOR_SHIFT) - 1;

// ╒════════╤═══════════════════ Colors ═══════════════════════════╕
// │ Color │ Meaning │
Expand Down
10 changes: 8 additions & 2 deletions std/assembly/rt/tlsf.ts
@@ -1,5 +1,6 @@
import { AL_BITS, AL_MASK, DEBUG, BLOCK, BLOCK_OVERHEAD, BLOCK_MAXSIZE } from "rt/common";
import { onfree, onalloc } from "./rtrace";
import { REFCOUNT_MASK } from "./pure";

/////////////////////// The TLSF (Two-Level Segregate Fit) memory allocator ///////////////////////
// see: http://www.gii.upv.es/tlsf/
Expand Down Expand Up @@ -490,7 +491,12 @@ 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
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 @@ -517,11 +523,11 @@ export function reallocateBlock(root: Root, block: Block, size: usize): Block {

// otherwise move the block
var newBlock = allocateBlock(root, size);
newBlock.gcInfo = block.gcInfo;
newBlock.rtId = block.rtId;
memory.copy(changetype<usize>(newBlock) + BLOCK_OVERHEAD, changetype<usize>(block) + BLOCK_OVERHEAD, size);
block.mmInfo = blockInfo | FREE;
insertBlock(root, block);
if (isDefined(ASC_RTRACE)) onfree(block);
return newBlock;
}

Expand Down
42 changes: 21 additions & 21 deletions tests/compiler/rc/global-init.optimized.wat
Expand Up @@ -94,7 +94,7 @@
if
i32.const 0
i32.const 88
i32.const 276
i32.const 277
i32.const 13
call $~lib/builtins/abort
unreachable
Expand All @@ -116,7 +116,7 @@
if
i32.const 0
i32.const 88
i32.const 278
i32.const 279
i32.const 13
call $~lib/builtins/abort
unreachable
Expand Down Expand Up @@ -161,7 +161,7 @@
if
i32.const 0
i32.const 88
i32.const 291
i32.const 292
i32.const 13
call $~lib/builtins/abort
unreachable
Expand Down Expand Up @@ -258,7 +258,7 @@
if
i32.const 0
i32.const 88
i32.const 204
i32.const 205
i32.const 13
call $~lib/builtins/abort
unreachable
Expand All @@ -272,7 +272,7 @@
if
i32.const 0
i32.const 88
i32.const 206
i32.const 207
i32.const 13
call $~lib/builtins/abort
unreachable
Expand Down Expand Up @@ -345,7 +345,7 @@
if
i32.const 0
i32.const 88
i32.const 227
i32.const 228
i32.const 15
call $~lib/builtins/abort
unreachable
Expand Down Expand Up @@ -402,7 +402,7 @@
if
i32.const 0
i32.const 88
i32.const 242
i32.const 243
i32.const 13
call $~lib/builtins/abort
unreachable
Expand All @@ -417,7 +417,7 @@
if
i32.const 0
i32.const 88
i32.const 243
i32.const 244
i32.const 13
call $~lib/builtins/abort
unreachable
Expand Down Expand Up @@ -467,7 +467,7 @@
if
i32.const 0
i32.const 88
i32.const 259
i32.const 260
i32.const 13
call $~lib/builtins/abort
unreachable
Expand Down Expand Up @@ -541,7 +541,7 @@
if
i32.const 0
i32.const 88
i32.const 531
i32.const 537
i32.const 2
call $~lib/builtins/abort
unreachable
Expand Down Expand Up @@ -599,7 +599,7 @@
if
i32.const 0
i32.const 88
i32.const 385
i32.const 386
i32.const 4
call $~lib/builtins/abort
unreachable
Expand All @@ -616,7 +616,7 @@
if
i32.const 0
i32.const 88
i32.const 395
i32.const 396
i32.const 15
call $~lib/builtins/abort
unreachable
Expand Down Expand Up @@ -644,7 +644,7 @@
if
i32.const 0
i32.const 88
i32.const 407
i32.const 408
i32.const 4
call $~lib/builtins/abort
unreachable
Expand Down Expand Up @@ -781,7 +781,7 @@
if
i32.const 232
i32.const 88
i32.const 447
i32.const 448
i32.const 29
call $~lib/builtins/abort
unreachable
Expand Down Expand Up @@ -856,7 +856,7 @@
if
i32.const 0
i32.const 88
i32.const 337
i32.const 338
i32.const 13
call $~lib/builtins/abort
unreachable
Expand Down Expand Up @@ -908,7 +908,7 @@
if
i32.const 0
i32.const 88
i32.const 350
i32.const 351
i32.const 17
call $~lib/builtins/abort
unreachable
Expand Down Expand Up @@ -978,7 +978,7 @@
if
i32.const 0
i32.const 88
i32.const 364
i32.const 365
i32.const 13
call $~lib/builtins/abort
unreachable
Expand Down Expand Up @@ -1064,7 +1064,7 @@
if
i32.const 0
i32.const 88
i32.const 477
i32.const 478
i32.const 15
call $~lib/builtins/abort
unreachable
Expand All @@ -1079,7 +1079,7 @@
if
i32.const 0
i32.const 88
i32.const 479
i32.const 480
i32.const 13
call $~lib/builtins/abort
unreachable
Expand Down Expand Up @@ -1302,7 +1302,7 @@
if
i32.const 0
i32.const 88
i32.const 561
i32.const 567
i32.const 13
call $~lib/builtins/abort
unreachable
Expand All @@ -1318,7 +1318,7 @@
if
i32.const 0
i32.const 88
i32.const 562
i32.const 568
i32.const 2
call $~lib/builtins/abort
unreachable
Expand Down

0 comments on commit 49edefc

Please sign in to comment.