Skip to content

Commit 49edefc

Browse files
committed
Fix invalid reference counts after internal realloc, see AssemblyScript#672
Previously realloc falsely copied the RC of the old block and missed to inform rtrace of the implicit free
1 parent f48f3c9 commit 49edefc

35 files changed

+794
-747
lines changed

src/builtins.ts

Lines changed: 14 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4060,14 +4060,14 @@ export function compileVisitMembers(compiler: Compiler): void {
40604060
assert(id == lastId++);
40614061

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

40644065
// if a library element, check if it implements a custom traversal function
40654066
if (instance.isDeclaredInLibrary && (visitImpl = instance.lookupInSelf("__visit_impl"))) {
40664067
assert(visitImpl.kind == ElementKind.FUNCTION_PROTOTYPE);
40674068
let visitFunc = program.resolver.resolveFunction(<FunctionPrototype>visitImpl, null);
4068-
let block: RelooperBlockRef;
40694069
if (!visitFunc || !compiler.compileFunction(visitFunc)) {
4070-
block = relooper.addBlock(
4070+
code.push(
40714071
module.unreachable()
40724072
);
40734073
} else {
@@ -4078,26 +4078,16 @@ export function compileVisitMembers(compiler: Compiler): void {
40784078
visitSig.returnType == Type.void &&
40794079
visitSig.thisType == instance.type
40804080
);
4081-
let callExpr = module.call(visitFunc.internalName, [
4082-
module.local_get(0, nativeSizeType), // ref
4083-
module.local_get(1, NativeType.I32) // cookie
4084-
], NativeType.None);
4085-
block = relooper.addBlock(
4086-
instance.base
4087-
? callExpr // branch will be added later
4088-
: module.block(null, [
4089-
callExpr,
4090-
module.return()
4091-
])
4081+
code.push(
4082+
module.call(visitFunc.internalName, [
4083+
module.local_get(0, nativeSizeType), // ref
4084+
module.local_get(1, NativeType.I32) // cookie
4085+
], NativeType.None)
40924086
);
40934087
}
4094-
relooper.addBranchForSwitch(outer, block, [ id ]);
4095-
blocks.push(block);
40964088

4097-
// otherwise generate one
4089+
// otherwise generate traversal logic for own fields
40984090
} else {
4099-
// traverse references assigned to own fields
4100-
let code = new Array<ExpressionRef>();
41014091
let members = instance.members;
41024092
if (members) {
41034093
for (let member of members.values()) {
@@ -4127,13 +4117,13 @@ export function compileVisitMembers(compiler: Compiler): void {
41274117
}
41284118
}
41294119
}
4130-
if (!instance.base) code.push(module.return());
4131-
let block = relooper.addBlock(
4132-
flatten(module, code, NativeType.None)
4133-
);
4134-
relooper.addBranchForSwitch(outer, block, [ id ]);
4135-
blocks.push(block);
41364120
}
4121+
if (!instance.base) code.push(module.return());
4122+
let block = relooper.addBlock(
4123+
flatten(module, code, NativeType.None)
4124+
);
4125+
relooper.addBranchForSwitch(outer, block, [ id ]);
4126+
blocks.push(block);
41374127
}
41384128
for (let [id, instance] of managedClasses) {
41394129
let base = instance.base;

std/assembly/rt/pure.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import { onincrement, ondecrement, onfree, onalloc } from "./rtrace";
2323
// @ts-ignore: decorator
2424
@inline const COLOR_MASK: u32 = ((1 << COLOR_BITS) - 1) << COLOR_SHIFT;
2525
// @ts-ignore: decorator
26-
@inline const REFCOUNT_MASK: u32 = (1 << COLOR_SHIFT) - 1;
26+
@inline export const REFCOUNT_MASK: u32 = (1 << COLOR_SHIFT) - 1;
2727

2828
// ╒════════╤═══════════════════ Colors ═══════════════════════════╕
2929
// │ Color │ Meaning │

std/assembly/rt/tlsf.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { AL_BITS, AL_MASK, DEBUG, BLOCK, BLOCK_OVERHEAD, BLOCK_MAXSIZE } from "rt/common";
22
import { onfree, onalloc } from "./rtrace";
3+
import { REFCOUNT_MASK } from "./pure";
34

45
/////////////////////// The TLSF (Two-Level Segregate Fit) memory allocator ///////////////////////
56
// see: http://www.gii.upv.es/tlsf/
@@ -490,7 +491,12 @@ export function allocateBlock(root: Root, size: usize): Block {
490491
export function reallocateBlock(root: Root, block: Block, size: usize): Block {
491492
var payloadSize = prepareSize(size);
492493
var blockInfo = block.mmInfo;
493-
if (DEBUG) assert(!(blockInfo & FREE)); // must be used
494+
if (DEBUG) {
495+
assert(
496+
!(blockInfo & FREE) && // must be used
497+
!(block.gcInfo & ~REFCOUNT_MASK) // not buffered or != BLACK
498+
);
499+
}
494500

495501
// possibly split and update runtime size if it still fits
496502
if (payloadSize <= (blockInfo & ~TAGS_MASK)) {
@@ -517,11 +523,11 @@ export function reallocateBlock(root: Root, block: Block, size: usize): Block {
517523

518524
// otherwise move the block
519525
var newBlock = allocateBlock(root, size);
520-
newBlock.gcInfo = block.gcInfo;
521526
newBlock.rtId = block.rtId;
522527
memory.copy(changetype<usize>(newBlock) + BLOCK_OVERHEAD, changetype<usize>(block) + BLOCK_OVERHEAD, size);
523528
block.mmInfo = blockInfo | FREE;
524529
insertBlock(root, block);
530+
if (isDefined(ASC_RTRACE)) onfree(block);
525531
return newBlock;
526532
}
527533

tests/compiler/rc/global-init.optimized.wat

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@
9494
if
9595
i32.const 0
9696
i32.const 88
97-
i32.const 276
97+
i32.const 277
9898
i32.const 13
9999
call $~lib/builtins/abort
100100
unreachable
@@ -116,7 +116,7 @@
116116
if
117117
i32.const 0
118118
i32.const 88
119-
i32.const 278
119+
i32.const 279
120120
i32.const 13
121121
call $~lib/builtins/abort
122122
unreachable
@@ -161,7 +161,7 @@
161161
if
162162
i32.const 0
163163
i32.const 88
164-
i32.const 291
164+
i32.const 292
165165
i32.const 13
166166
call $~lib/builtins/abort
167167
unreachable
@@ -258,7 +258,7 @@
258258
if
259259
i32.const 0
260260
i32.const 88
261-
i32.const 204
261+
i32.const 205
262262
i32.const 13
263263
call $~lib/builtins/abort
264264
unreachable
@@ -272,7 +272,7 @@
272272
if
273273
i32.const 0
274274
i32.const 88
275-
i32.const 206
275+
i32.const 207
276276
i32.const 13
277277
call $~lib/builtins/abort
278278
unreachable
@@ -345,7 +345,7 @@
345345
if
346346
i32.const 0
347347
i32.const 88
348-
i32.const 227
348+
i32.const 228
349349
i32.const 15
350350
call $~lib/builtins/abort
351351
unreachable
@@ -402,7 +402,7 @@
402402
if
403403
i32.const 0
404404
i32.const 88
405-
i32.const 242
405+
i32.const 243
406406
i32.const 13
407407
call $~lib/builtins/abort
408408
unreachable
@@ -417,7 +417,7 @@
417417
if
418418
i32.const 0
419419
i32.const 88
420-
i32.const 243
420+
i32.const 244
421421
i32.const 13
422422
call $~lib/builtins/abort
423423
unreachable
@@ -467,7 +467,7 @@
467467
if
468468
i32.const 0
469469
i32.const 88
470-
i32.const 259
470+
i32.const 260
471471
i32.const 13
472472
call $~lib/builtins/abort
473473
unreachable
@@ -541,7 +541,7 @@
541541
if
542542
i32.const 0
543543
i32.const 88
544-
i32.const 531
544+
i32.const 537
545545
i32.const 2
546546
call $~lib/builtins/abort
547547
unreachable
@@ -599,7 +599,7 @@
599599
if
600600
i32.const 0
601601
i32.const 88
602-
i32.const 385
602+
i32.const 386
603603
i32.const 4
604604
call $~lib/builtins/abort
605605
unreachable
@@ -616,7 +616,7 @@
616616
if
617617
i32.const 0
618618
i32.const 88
619-
i32.const 395
619+
i32.const 396
620620
i32.const 15
621621
call $~lib/builtins/abort
622622
unreachable
@@ -644,7 +644,7 @@
644644
if
645645
i32.const 0
646646
i32.const 88
647-
i32.const 407
647+
i32.const 408
648648
i32.const 4
649649
call $~lib/builtins/abort
650650
unreachable
@@ -781,7 +781,7 @@
781781
if
782782
i32.const 232
783783
i32.const 88
784-
i32.const 447
784+
i32.const 448
785785
i32.const 29
786786
call $~lib/builtins/abort
787787
unreachable
@@ -856,7 +856,7 @@
856856
if
857857
i32.const 0
858858
i32.const 88
859-
i32.const 337
859+
i32.const 338
860860
i32.const 13
861861
call $~lib/builtins/abort
862862
unreachable
@@ -908,7 +908,7 @@
908908
if
909909
i32.const 0
910910
i32.const 88
911-
i32.const 350
911+
i32.const 351
912912
i32.const 17
913913
call $~lib/builtins/abort
914914
unreachable
@@ -978,7 +978,7 @@
978978
if
979979
i32.const 0
980980
i32.const 88
981-
i32.const 364
981+
i32.const 365
982982
i32.const 13
983983
call $~lib/builtins/abort
984984
unreachable
@@ -1064,7 +1064,7 @@
10641064
if
10651065
i32.const 0
10661066
i32.const 88
1067-
i32.const 477
1067+
i32.const 478
10681068
i32.const 15
10691069
call $~lib/builtins/abort
10701070
unreachable
@@ -1079,7 +1079,7 @@
10791079
if
10801080
i32.const 0
10811081
i32.const 88
1082-
i32.const 479
1082+
i32.const 480
10831083
i32.const 13
10841084
call $~lib/builtins/abort
10851085
unreachable
@@ -1302,7 +1302,7 @@
13021302
if
13031303
i32.const 0
13041304
i32.const 88
1305-
i32.const 561
1305+
i32.const 567
13061306
i32.const 13
13071307
call $~lib/builtins/abort
13081308
unreachable
@@ -1318,7 +1318,7 @@
13181318
if
13191319
i32.const 0
13201320
i32.const 88
1321-
i32.const 562
1321+
i32.const 568
13221322
i32.const 2
13231323
call $~lib/builtins/abort
13241324
unreachable

0 commit comments

Comments
 (0)