Skip to content

Commit 289ddb7

Browse files
authored
Add realloc support to rtrace (#1062)
1 parent 03bb15e commit 289ddb7

Some content is hidden

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

53 files changed

+3176
-3114
lines changed

lib/rtrace/index.d.ts

Lines changed: 48 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,82 +1,63 @@
1-
/**
2-
* This method returns an `RTrace` object used for reference count tracing.
3-
*
4-
* @param {TraceEventCallback?} onerror - A method that is called when a trace error event occurs.
5-
* @param {TraceEventCallback?} oninfo - A method that is called when a trace info event occurs.
6-
*/
7-
declare function rtrace(onerror?: rtrace.TraceEventCallback, oninfo?: rtrace.TraceEventCallback): rtrace.RTrace;
1+
/** Creates a new `RTrace` instance, tracking allocations, frees and reference counts. */
2+
declare function rtrace(
3+
/** Function being called when a problem is detected. */
4+
onerror?: (error: Error) => void,
5+
/** Function being called with information messages. */
6+
oninfo?: (info: string) => void
7+
): rtrace.RTrace;
88

99
declare namespace rtrace {
10-
/**
11-
* The RTrace interface represents a collection of properties that help develoeprs describe the
12-
* reference counts and state of the Web Assembly module.
13-
*/
10+
/** The rtrace instance used as the `rtrace` import to the Wasm module. */
1411
export interface RTrace {
15-
16-
/**
17-
* The current allocation count.
18-
*/
12+
/** Number of allocations so far. */
1913
allocCount: number;
20-
21-
/**
22-
* The current free count.
23-
*/
14+
/** Number of reallocations so far. */
15+
reallocCount: number;
16+
/** Number of frees so far. */
2417
freeCount: number;
25-
26-
/**
27-
* The current increment count.
28-
*/
18+
/** Number of RC increments (retains) so far. */
2919
incrementCount: number;
30-
31-
/**
32-
* The current decrement count.
33-
*/
20+
/** Number of RC decrements (releases) so far. */
3421
decrementCount: number;
3522

36-
/**
37-
* This method is called when an allocation occurs.
38-
*
39-
* @param {number} block - The `ptr - 16` value indicating the start of the block.
40-
*/
41-
onalloc(block: number): void;
42-
43-
/**
44-
* This method is called when a block is freed.
45-
*
46-
* @param {number} block - The `ptr - 16` value indicating the start of the block.
47-
*/
48-
onfree(block: number): void;
49-
50-
/**
51-
* This method is called when a reference count is incrememnted
52-
*
53-
* @param {number} block - The `ptr - 16` value indicating the start of the block.
54-
*/
55-
onincrement(block: number): void;
56-
57-
/**
58-
* This method is called when a reference count is decremented.
59-
*
60-
* @param {number} block - The `ptr - 16` value indicating the start of the block.
61-
*/
62-
ondecrement(block: number): void;
63-
64-
/**
65-
* This property indicates if rtrace is active.
66-
*/
23+
/** Called when a new block is allocated. */
24+
onalloc(
25+
/** New block being allocated. */
26+
block: number
27+
): void;
28+
29+
/** Called when a block is reallocated and must be moved. */
30+
onrealloc(
31+
/** Block being moved. */
32+
oldBlock: number,
33+
/** New block used from now on. */
34+
newBlock: number
35+
): void;
36+
37+
/** Called when a block is freed, implicitly or explicitly. */
38+
onfree(
39+
/** Block being freed. */
40+
block: number
41+
): void;
42+
43+
/** Called when a reference to a block is retained (RC incremented by one). */
44+
onincrement(
45+
/** Block a reference to is being retained. */
46+
block: number
47+
): void;
48+
49+
/** Called when a reference to a block is released (RC decremented by one). */
50+
ondecrement(
51+
/** Block a reference to is being released. */
52+
block: number
53+
): void;
54+
55+
/** Checks if rtrace is active, i.e. at least one event has occurred. */
6756
readonly active: boolean;
6857

69-
/**
70-
* This method returns the current number of allocated blocks.
71-
*/
58+
/** Checks if there are any leaks and emits them via `oninfo`. Returns the number of live blocks. */
7259
check(): number;
73-
7460
}
75-
76-
/**
77-
* This is a trace event callback. It accepts a string containing a message about the event.
78-
*/
79-
export type TraceEventCallback = (info: string) => void;
8061
}
8162

8263
export = rtrace;

lib/rtrace/index.js

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ function rtrace(onerror, oninfo) {
55
var rtrace = {
66

77
allocCount: 0,
8+
reallocCount: 0,
89
freeCount: 0,
910
incrementCount: 0,
1011
decrementCount: 0,
@@ -19,6 +20,26 @@ function rtrace(onerror, oninfo) {
1920
}
2021
},
2122

23+
onrealloc: function(oldBlock, newBlock) {
24+
++rtrace.reallocCount;
25+
if (!blocks.has(oldBlock)) {
26+
onerror(Error("orphaned realloc (old): " + oldBlock));
27+
} else {
28+
if (!blocks.has(newBlock)) {
29+
onerror(Error("orphaned realloc (new): " + newBlock));
30+
} else {
31+
let newRc = blocks.get(newBlock);
32+
if (newRc != 0) {
33+
onerror(Error("invalid realloc: " + oldBlock + " -> " + newBlock + " @ " + newRc));
34+
} else {
35+
let oldRc = blocks.get(oldBlock);
36+
oninfo("REALLOC " + oldBlock + " @ " + oldRc + " -> " + newBlock);
37+
blocks.set(newBlock, oldRc);
38+
}
39+
}
40+
}
41+
},
42+
2243
onfree: function(block) {
2344
++rtrace.freeCount;
2445
if (!blocks.has(block)) {
@@ -47,7 +68,7 @@ function rtrace(onerror, oninfo) {
4768
} else {
4869
let rc = blocks.get(block);
4970
if (rc < 1) {
50-
onerror(Error("invalid decrement: " + block));
71+
onerror(Error("invalid decrement: " + block + " @ " + rc));
5172
} else {
5273
oninfo("-- " + block + " @ " + rc + "->" + (rc - 1));
5374
blocks.set(block, rc - 1);
@@ -56,7 +77,7 @@ function rtrace(onerror, oninfo) {
5677
},
5778

5879
get active() {
59-
return Boolean(rtrace.allocCount || rtrace.freeCount || rtrace.incrementCount || rtrace.decrementCount);
80+
return Boolean(rtrace.allocCount || rtrace.reallocCount || rtrace.freeCount || rtrace.incrementCount || rtrace.decrementCount);
6081
},
6182

6283
check() {

std/assembly/rt/rtrace.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { BLOCK } from "./common";
22

33
export declare function onalloc(s: BLOCK): void;
4+
export declare function onrealloc(sOld: BLOCK, sNew: BLOCK): void;
45
export declare function onincrement(s: BLOCK): void;
56
export declare function ondecrement(s: BLOCK): void;
67
export declare function onfree(s: BLOCK): void;

std/assembly/rt/tlsf.ts

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

55
/////////////////////// The TLSF (Two-Level Segregate Fit) memory allocator ///////////////////////
@@ -549,7 +549,10 @@ export function reallocateBlock(root: Root, block: Block, size: usize): Block {
549549
var newBlock = allocateBlock(root, size, block.rtId); // may invalidate cached blockInfo
550550
newBlock.gcInfo = block.gcInfo; // keep RC
551551
memory.copy(changetype<usize>(newBlock) + BLOCK_OVERHEAD, changetype<usize>(block) + BLOCK_OVERHEAD, size);
552-
if (changetype<usize>(block) >= __heap_base) freeBlock(root, block);
552+
if (changetype<usize>(block) >= __heap_base) {
553+
if (isDefined(ASC_RTRACE)) onrealloc(block, newBlock);
554+
freeBlock(root, block);
555+
}
553556
return newBlock;
554557
}
555558

tests/compiler/do.optimized.wat

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1835,7 +1835,7 @@
18351835
if
18361836
i32.const 0
18371837
i32.const 64
1838-
i32.const 567
1838+
i32.const 570
18391839
i32.const 2
18401840
call $~lib/builtins/abort
18411841
unreachable

tests/compiler/do.untouched.wat

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3445,7 +3445,7 @@
34453445
if
34463446
i32.const 0
34473447
i32.const 64
3448-
i32.const 567
3448+
i32.const 570
34493449
i32.const 2
34503450
call $~lib/builtins/abort
34513451
unreachable

tests/compiler/extends-baseaggregate.optimized.wat

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1405,7 +1405,7 @@
14051405
if
14061406
i32.const 0
14071407
i32.const 128
1408-
i32.const 567
1408+
i32.const 570
14091409
i32.const 2
14101410
call $~lib/builtins/abort
14111411
unreachable

tests/compiler/extends-baseaggregate.untouched.wat

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1806,7 +1806,7 @@
18061806
if
18071807
i32.const 0
18081808
i32.const 128
1809-
i32.const 567
1809+
i32.const 570
18101810
i32.const 2
18111811
call $~lib/builtins/abort
18121812
unreachable

tests/compiler/for.optimized.wat

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1855,7 +1855,7 @@
18551855
if
18561856
i32.const 0
18571857
i32.const 64
1858-
i32.const 567
1858+
i32.const 570
18591859
i32.const 2
18601860
call $~lib/builtins/abort
18611861
unreachable

tests/compiler/for.untouched.wat

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3479,7 +3479,7 @@
34793479
if
34803480
i32.const 0
34813481
i32.const 64
3482-
i32.const 567
3482+
i32.const 570
34833483
i32.const 2
34843484
call $~lib/builtins/abort
34853485
unreachable

0 commit comments

Comments
 (0)