warpo 3.0.0 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/debug_server/debugSession.d.ts +17 -1
- package/dist/debug_server/debugSession.js +169 -7
- package/dist/debug_server/debugSession.js.map +1 -1
- package/dist/debug_server/debugger.d.ts +25 -0
- package/dist/debug_server/debugger.js +4 -0
- package/dist/debug_server/debugger.js.map +1 -0
- package/dist/debug_server/debuggerWasmModule.d.ts +28 -0
- package/dist/debug_server/debuggerWasmModule.js +75 -0
- package/dist/debug_server/debuggerWasmModule.js.map +1 -0
- package/dist/debug_server/nodeDebugger.d.ts +27 -0
- package/dist/debug_server/nodeDebugger.js +240 -0
- package/dist/debug_server/nodeDebugger.js.map +1 -0
- package/dist/debug_server/tests/debugSession.test.js +45 -1
- package/dist/debug_server/tests/debugSession.test.js.map +1 -1
- package/dist/debug_server/tests/testModule/debugger_basic.d.ts +1 -0
- package/dist/debug_server/tests/testModule/debugger_basic.js +6 -0
- package/dist/debug_server/tests/testModule/debugger_basic.js.map +1 -0
- package/dist/debug_server/wasmEntry.js +36 -0
- package/dist/debug_server/wasmEntry.js.map +1 -0
- package/dist/heap_analyzer/src/comparison.d.ts +2 -0
- package/dist/heap_analyzer/src/comparison.js +77 -0
- package/dist/heap_analyzer/src/comparison.js.map +1 -0
- package/dist/heap_analyzer/src/constants.d.ts +1 -1
- package/dist/heap_analyzer/src/constants.js +1 -1
- package/dist/heap_analyzer/src/debugInfoResolver.d.ts +30 -0
- package/dist/heap_analyzer/src/debugInfoResolver.js +334 -0
- package/dist/heap_analyzer/src/debugInfoResolver.js.map +1 -0
- package/dist/heap_analyzer/src/dumpReader.js +11 -2
- package/dist/heap_analyzer/src/dumpReader.js.map +1 -1
- package/dist/heap_analyzer/src/dwarfParser.d.ts +30 -9
- package/dist/heap_analyzer/src/dwarfParser.js +54 -20
- package/dist/heap_analyzer/src/dwarfParser.js.map +1 -1
- package/dist/heap_analyzer/src/index.d.ts +7 -0
- package/dist/heap_analyzer/src/index.js +16 -0
- package/dist/heap_analyzer/src/index.js.map +1 -0
- package/dist/heap_analyzer/src/referenceScanner.d.ts +4 -4
- package/dist/heap_analyzer/src/referenceScanner.js +52 -21
- package/dist/heap_analyzer/src/referenceScanner.js.map +1 -1
- package/dist/heap_analyzer/src/roots.d.ts +3 -6
- package/dist/heap_analyzer/src/roots.js +12 -5
- package/dist/heap_analyzer/src/roots.js.map +1 -1
- package/dist/heap_analyzer/src/snapshot.d.ts +2 -2
- package/dist/heap_analyzer/src/snapshot.js +36 -88
- package/dist/heap_analyzer/src/snapshot.js.map +1 -1
- package/dist/heap_analyzer/src/types.d.ts +54 -11
- package/dist/heap_analyzer/src/types.js +22 -1
- package/dist/heap_analyzer/src/types.js.map +1 -1
- package/dist/heap_analyzer/tests/comparison.test.d.ts +1 -0
- package/dist/heap_analyzer/tests/comparison.test.js +121 -0
- package/dist/heap_analyzer/tests/comparison.test.js.map +1 -0
- package/dist/heap_analyzer/tests/debugInfoResolver.test.d.ts +1 -0
- package/dist/heap_analyzer/tests/debugInfoResolver.test.js +205 -0
- package/dist/heap_analyzer/tests/debugInfoResolver.test.js.map +1 -0
- package/dist/heap_analyzer/tests/dumpReader.test.js +12 -2
- package/dist/heap_analyzer/tests/dumpReader.test.js.map +1 -1
- package/dist/heap_analyzer/tests/dwarfParser.test.js +40 -28
- package/dist/heap_analyzer/tests/dwarfParser.test.js.map +1 -1
- package/dist/heap_analyzer/tests/roots.test.js +21 -4
- package/dist/heap_analyzer/tests/roots.test.js.map +1 -1
- package/dist/heap_analyzer/tests/snapshot.test.js +58 -54
- package/dist/heap_analyzer/tests/snapshot.test.js.map +1 -1
- package/dist/heap_analyzer/tests/testHelper.js +1 -1
- package/dist/heap_analyzer/tests/testHelper.js.map +1 -1
- package/dist/heap_analyzer/tests/wasmExecutor.js +2 -1
- package/dist/heap_analyzer/tests/wasmExecutor.js.map +1 -1
- package/dist/scripts/lib.d.ts +5 -1
- package/dist/scripts/lib.js +171 -24
- package/dist/scripts/lib.js.map +1 -1
- package/dist/test_runner/core/compiler.js +0 -1
- package/dist/test_runner/core/compiler.js.map +1 -1
- package/dist/warpo.d.ts +12 -1
- package/dist/warpo.js +32 -7
- package/dist/warpo.js.map +1 -1
- package/dist/warpo_internal.d.ts +1 -1
- package/dist/warpo_internal.js +23 -14
- package/dist/warpo_internal.js.map +1 -1
- package/package.json +9 -1
- package/dist/heap_analyzer/src/classResolver.d.ts +0 -34
- package/dist/heap_analyzer/src/classResolver.js +0 -206
- package/dist/heap_analyzer/src/classResolver.js.map +0 -1
- package/dist/heap_analyzer/tests/classResolver.test.js +0 -110
- package/dist/heap_analyzer/tests/classResolver.test.js.map +0 -1
- /package/dist/{heap_analyzer/tests/classResolver.test.d.ts → debug_server/wasmEntry.d.ts} +0 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { HeapComparison, HeapSnapshot } from "./types.js";
|
|
2
|
+
export declare function analyzeDump(dumpBuffer: ArrayBuffer, wasmBinary: Uint8Array | ArrayBuffer): HeapSnapshot;
|
|
3
|
+
export declare function compareDumps(beforeDumpBuffer: ArrayBuffer, afterDumpBuffer: ArrayBuffer, wasmBinary: Uint8Array | ArrayBuffer): HeapComparison;
|
|
4
|
+
export { analyzeHeap } from "./snapshot.js";
|
|
5
|
+
export { compareSnapshots } from "./comparison.js";
|
|
6
|
+
export { parseDumpFile } from "./dumpReader.js";
|
|
7
|
+
export type { BuiltinContainerKind, ClassField, ClassLayout, ComparisonInstance, ComparisonInstanceChangeKind, ConstructorComparisonEntry, ConstructorEntry, ConstructorInstance, DumpedMemory, EntryLayout, GlobalRoot, HeapComparison, HeapObject, HeapSnapshot, ObjectHeader, RootInfo, RootType, RuntimeGlobalValues, } from "./types.js";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// Copyright (C) 2026 wasm-ecosystem
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { compareSnapshots } from "./comparison.js";
|
|
4
|
+
import { parseDumpFile } from "./dumpReader.js";
|
|
5
|
+
import { analyzeHeap } from "./snapshot.js";
|
|
6
|
+
export function analyzeDump(dumpBuffer, wasmBinary) {
|
|
7
|
+
const dumpedMemory = parseDumpFile(dumpBuffer);
|
|
8
|
+
return analyzeHeap(dumpedMemory.memory, dumpedMemory.rtGlobals, wasmBinary);
|
|
9
|
+
}
|
|
10
|
+
export function compareDumps(beforeDumpBuffer, afterDumpBuffer, wasmBinary) {
|
|
11
|
+
return compareSnapshots(analyzeDump(beforeDumpBuffer, wasmBinary), analyzeDump(afterDumpBuffer, wasmBinary));
|
|
12
|
+
}
|
|
13
|
+
export { analyzeHeap } from "./snapshot.js";
|
|
14
|
+
export { compareSnapshots } from "./comparison.js";
|
|
15
|
+
export { parseDumpFile } from "./dumpReader.js";
|
|
16
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../tools/heap_analyzer/src/index.ts"],"names":[],"mappings":"AAAA,oCAAoC;AACpC,sCAAsC;AAEtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAG5C,MAAM,UAAU,WAAW,CAAC,UAAuB,EAAE,UAAoC;IACvF,MAAM,YAAY,GAAG,aAAa,CAAC,UAAU,CAAC,CAAC;IAC/C,OAAO,WAAW,CAAC,YAAY,CAAC,MAAM,EAAE,YAAY,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;AAC9E,CAAC;AAED,MAAM,UAAU,YAAY,CAC1B,gBAA6B,EAC7B,eAA4B,EAC5B,UAAoC;IAEpC,OAAO,gBAAgB,CAAC,WAAW,CAAC,gBAAgB,EAAE,UAAU,CAAC,EAAE,WAAW,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC,CAAC;AAC/G,CAAC;AAED,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import type {
|
|
1
|
+
import { type ObjectHeader } from "./types.js";
|
|
2
|
+
import type { DebugInfoResolver } from "./debugInfoResolver.js";
|
|
3
3
|
/**
|
|
4
4
|
* Scan object payloads to build a precise reference graph using debug info.
|
|
5
5
|
*
|
|
6
6
|
* @param memory Header-stripped DataView (wasm addr 0 = offset 0)
|
|
7
7
|
* @param objects Parsed object headers from parseAllObjects
|
|
8
|
-
* @param
|
|
8
|
+
* @param debugInfoResolver DebugInfoResolver built from debug info
|
|
9
9
|
* @returns Adjacency list: payloadPtr → array of referenced payloadPtrs
|
|
10
10
|
*/
|
|
11
|
-
export declare function scanReferences(memory: DataView, objects: ObjectHeader[],
|
|
11
|
+
export declare function scanReferences(memory: DataView, objects: ObjectHeader[], debugInfoResolver: DebugInfoResolver): Map<number, number[]>;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// Copyright (C) 2026 wasm-ecosystem
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { BuiltinContainerKind, getReferenceFields, isPointerfree, } from "./types.js";
|
|
3
4
|
function readValidPtr(memory, addr, validPtrs) {
|
|
4
5
|
if (addr + 4 > memory.byteLength) {
|
|
5
6
|
return null;
|
|
@@ -10,8 +11,8 @@ function readValidPtr(memory, addr, validPtrs) {
|
|
|
10
11
|
}
|
|
11
12
|
return ptr;
|
|
12
13
|
}
|
|
13
|
-
function scanReferenceFields(memory, obj,
|
|
14
|
-
for (const field of
|
|
14
|
+
function scanReferenceFields(memory, obj, classLayout, validPtrs, edges) {
|
|
15
|
+
for (const field of getReferenceFields(classLayout)) {
|
|
15
16
|
if (field.offset + field.size > obj.rtSize) {
|
|
16
17
|
// Skip fields that don't fit within the object's size (could be a broken dumped memory or stale debug info)
|
|
17
18
|
continue;
|
|
@@ -100,22 +101,48 @@ function scanSmallTupleElements(memory, obj, validPtrs, edges) {
|
|
|
100
101
|
}
|
|
101
102
|
}
|
|
102
103
|
}
|
|
103
|
-
function
|
|
104
|
-
const
|
|
105
|
-
if (
|
|
106
|
-
scanArrayElements(memory, obj, validPtrs, edges);
|
|
104
|
+
function scanFunctionEnv(memory, obj, classLayout, validPtrs, edges) {
|
|
105
|
+
const envField = classLayout.fields.find((field) => field.name === "_env");
|
|
106
|
+
if (!envField || envField.offset + envField.size > obj.rtSize) {
|
|
107
107
|
return;
|
|
108
108
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
}
|
|
113
|
-
if (name === "~lib/tuple/SmallTuple") {
|
|
114
|
-
scanSmallTupleElements(memory, obj, validPtrs, edges);
|
|
115
|
-
return;
|
|
109
|
+
const ptr = readValidPtr(memory, obj.payloadPtr + envField.offset, validPtrs);
|
|
110
|
+
if (ptr !== null) {
|
|
111
|
+
edges.push(ptr);
|
|
116
112
|
}
|
|
117
|
-
|
|
118
|
-
|
|
113
|
+
}
|
|
114
|
+
function scanBuiltinContainer(memory, obj, classLayout, validPtrs, edges) {
|
|
115
|
+
scanReferenceFields(memory, obj, classLayout, validPtrs, edges);
|
|
116
|
+
switch (classLayout.builtinKind) {
|
|
117
|
+
case BuiltinContainerKind.Array: {
|
|
118
|
+
if (classLayout.templateTypeIsReference === true) {
|
|
119
|
+
scanArrayElements(memory, obj, validPtrs, edges);
|
|
120
|
+
}
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
case BuiltinContainerKind.StaticArray: {
|
|
124
|
+
if (classLayout.templateTypeIsReference === true) {
|
|
125
|
+
scanStaticArrayElements(memory, obj, validPtrs, edges);
|
|
126
|
+
}
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
case BuiltinContainerKind.SmallTuple: {
|
|
130
|
+
scanSmallTupleElements(memory, obj, validPtrs, edges);
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
case BuiltinContainerKind.Function: {
|
|
134
|
+
scanFunctionEnv(memory, obj, classLayout, validPtrs, edges);
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
case BuiltinContainerKind.MapOrSet: {
|
|
138
|
+
if (classLayout.entryLayout) {
|
|
139
|
+
scanSetMapEntries(memory, obj, classLayout.entryLayout, validPtrs, edges);
|
|
140
|
+
}
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
default: {
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
119
146
|
}
|
|
120
147
|
}
|
|
121
148
|
/**
|
|
@@ -123,18 +150,22 @@ function scanContainerElements(memory, obj, classLayout, validPtrs, edges) {
|
|
|
123
150
|
*
|
|
124
151
|
* @param memory Header-stripped DataView (wasm addr 0 = offset 0)
|
|
125
152
|
* @param objects Parsed object headers from parseAllObjects
|
|
126
|
-
* @param
|
|
153
|
+
* @param debugInfoResolver DebugInfoResolver built from debug info
|
|
127
154
|
* @returns Adjacency list: payloadPtr → array of referenced payloadPtrs
|
|
128
155
|
*/
|
|
129
|
-
export function scanReferences(memory, objects,
|
|
156
|
+
export function scanReferences(memory, objects, debugInfoResolver) {
|
|
130
157
|
const validPtrs = new Set(objects.map((o) => o.payloadPtr));
|
|
131
158
|
const graph = new Map();
|
|
132
159
|
for (const obj of objects) {
|
|
133
160
|
const edges = [];
|
|
134
|
-
const classLayout =
|
|
135
|
-
if (classLayout
|
|
136
|
-
|
|
137
|
-
|
|
161
|
+
const classLayout = debugInfoResolver.getClassDef(obj.rtId);
|
|
162
|
+
if (classLayout) {
|
|
163
|
+
if (classLayout.builtinKind !== undefined) {
|
|
164
|
+
scanBuiltinContainer(memory, obj, classLayout, validPtrs, edges);
|
|
165
|
+
}
|
|
166
|
+
else if (!isPointerfree(classLayout)) {
|
|
167
|
+
scanReferenceFields(memory, obj, classLayout, validPtrs, edges);
|
|
168
|
+
}
|
|
138
169
|
}
|
|
139
170
|
graph.set(obj.payloadPtr, edges);
|
|
140
171
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"referenceScanner.js","sourceRoot":"","sources":["../../../tools/heap_analyzer/src/referenceScanner.ts"],"names":[],"mappings":"AAAA,oCAAoC;AACpC,sCAAsC;
|
|
1
|
+
{"version":3,"file":"referenceScanner.js","sourceRoot":"","sources":["../../../tools/heap_analyzer/src/referenceScanner.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
import type { ObjectHeader, RootInfo,
|
|
1
|
+
import type { GlobalRoot, ObjectHeader, RootInfo, RuntimeGlobalValues } from "./types.js";
|
|
2
2
|
/**
|
|
3
3
|
* Identify GC roots that can be recovered reliably from the current dump model.
|
|
4
4
|
*
|
|
5
5
|
* Currently supported:
|
|
6
|
+
* - GC globals identified from DWARF + wasm global metadata
|
|
6
7
|
* - shadow stack roots
|
|
7
8
|
* - pinned objects (transparent GC color)
|
|
8
|
-
*
|
|
9
|
-
* Precise GC global-root detection is intentionally not implemented yet.
|
|
10
|
-
* Scanning arbitrary words in the static region would misclassify incidental
|
|
11
|
-
* pointer-like bytes from static strings or static arrays as semantic globals.
|
|
12
9
|
*/
|
|
13
|
-
export declare function findRoots(memory: DataView, rtGlobals:
|
|
10
|
+
export declare function findRoots(memory: DataView, rtGlobals: RuntimeGlobalValues, objects: ObjectHeader[], globalRoots?: GlobalRoot[]): RootInfo[];
|
|
@@ -5,16 +5,23 @@ import { GC_COLOR_TRANSPARENT } from "./constants.js";
|
|
|
5
5
|
* Identify GC roots that can be recovered reliably from the current dump model.
|
|
6
6
|
*
|
|
7
7
|
* Currently supported:
|
|
8
|
+
* - GC globals identified from DWARF + wasm global metadata
|
|
8
9
|
* - shadow stack roots
|
|
9
10
|
* - pinned objects (transparent GC color)
|
|
10
|
-
*
|
|
11
|
-
* Precise GC global-root detection is intentionally not implemented yet.
|
|
12
|
-
* Scanning arbitrary words in the static region would misclassify incidental
|
|
13
|
-
* pointer-like bytes from static strings or static arrays as semantic globals.
|
|
14
11
|
*/
|
|
15
|
-
export function findRoots(memory, rtGlobals, objects) {
|
|
12
|
+
export function findRoots(memory, rtGlobals, objects, globalRoots = []) {
|
|
16
13
|
const validPtrs = new Set(objects.map((obj) => obj.payloadPtr));
|
|
17
14
|
const roots = [];
|
|
15
|
+
for (const globalRoot of globalRoots) {
|
|
16
|
+
if (globalRoot.value !== 0 && validPtrs.has(globalRoot.value)) {
|
|
17
|
+
roots.push({
|
|
18
|
+
objectPtr: globalRoot.value,
|
|
19
|
+
className: "",
|
|
20
|
+
rootType: "global",
|
|
21
|
+
sourceAddress: globalRoot.globalIndex,
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
}
|
|
18
25
|
// Shadow stack in incremental runtime contains managed object pointers.
|
|
19
26
|
for (let addr = rtGlobals.stackPointer; addr < rtGlobals.heapBase; addr += 4) {
|
|
20
27
|
if (addr + 4 > memory.byteLength) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"roots.js","sourceRoot":"","sources":["../../../tools/heap_analyzer/src/roots.ts"],"names":[],"mappings":"AAAA,oCAAoC;AACpC,sCAAsC;AAEtC,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAGtD
|
|
1
|
+
{"version":3,"file":"roots.js","sourceRoot":"","sources":["../../../tools/heap_analyzer/src/roots.ts"],"names":[],"mappings":"AAAA,oCAAoC;AACpC,sCAAsC;AAEtC,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAGtD;;;;;;;GAOG;AACH,MAAM,UAAU,SAAS,CACvB,MAAgB,EAChB,SAA8B,EAC9B,OAAuB,EACvB,cAA4B,EAAE;IAE9B,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC;IAChE,MAAM,KAAK,GAAe,EAAE,CAAC;IAE7B,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;QACrC,IAAI,UAAU,CAAC,KAAK,KAAK,CAAC,IAAI,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;YAC9D,KAAK,CAAC,IAAI,CAAC;gBACT,SAAS,EAAE,UAAU,CAAC,KAAK;gBAC3B,SAAS,EAAE,EAAE;gBACb,QAAQ,EAAE,QAAQ;gBAClB,aAAa,EAAE,UAAU,CAAC,WAAW;aACtC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,wEAAwE;IACxE,KAAK,IAAI,IAAI,GAAG,SAAS,CAAC,YAAY,EAAE,IAAI,GAAG,SAAS,CAAC,QAAQ,EAAE,IAAI,IAAI,CAAC,EAAE,CAAC;QAC7E,IAAI,IAAI,GAAG,CAAC,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;YACjC,MAAM;QACR,CAAC;QAED,MAAM,GAAG,GAAG,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACzC,IAAI,GAAG,KAAK,CAAC,IAAI,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACpC,KAAK,CAAC,IAAI,CAAC;gBACT,SAAS,EAAE,GAAG;gBACd,SAAS,EAAE,EAAE;gBACb,QAAQ,EAAE,OAAO;gBACjB,aAAa,EAAE,IAAI;aACpB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;QAC1B,IAAI,GAAG,CAAC,OAAO,KAAK,oBAAoB,EAAE,CAAC;YACzC,KAAK,CAAC,IAAI,CAAC;gBACT,SAAS,EAAE,GAAG,CAAC,UAAU;gBACzB,SAAS,EAAE,EAAE;gBACb,QAAQ,EAAE,QAAQ;gBAClB,aAAa,EAAE,CAAC;aACjB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type { HeapSnapshot,
|
|
2
|
-
export declare function analyzeHeap(memory: DataView, rtGlobals:
|
|
1
|
+
import type { HeapSnapshot, RuntimeGlobalValues } from "./types.js";
|
|
2
|
+
export declare function analyzeHeap(memory: DataView, rtGlobals: RuntimeGlobalValues, wasmBinary: Uint8Array | ArrayBuffer): HeapSnapshot;
|
|
@@ -1,28 +1,21 @@
|
|
|
1
1
|
// Copyright (C) 2026 wasm-ecosystem
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
import { AL_MASK, BLOCK_OVERHEAD, ROOT_SIZE } from "./constants.js";
|
|
4
|
-
import {
|
|
4
|
+
import { DebugInfoResolver } from "./debugInfoResolver.js";
|
|
5
5
|
import { buildDominatorTree } from "./dominator.js";
|
|
6
6
|
import { computeRetainedSizes, shallowSize } from "./retainedSize.js";
|
|
7
7
|
import { findRoots } from "./roots.js";
|
|
8
8
|
import { scanReferences } from "./referenceScanner.js";
|
|
9
9
|
import { walkBlocks } from "./tlsf.js";
|
|
10
|
-
function getAssignedRootType(rootTypes, payloadPtr) {
|
|
11
|
-
const rootType = rootTypes.get(payloadPtr);
|
|
12
|
-
if (!rootType) {
|
|
13
|
-
throw new Error(`Missing root type for live object ${payloadPtr}`);
|
|
14
|
-
}
|
|
15
|
-
return rootType;
|
|
16
|
-
}
|
|
17
10
|
export function analyzeHeap(memory, rtGlobals, wasmBinary) {
|
|
18
|
-
// Resolve DWARF-derived class
|
|
19
|
-
const
|
|
11
|
+
// Resolve DWARF-derived class and global metadata once up front for the entire pipeline.
|
|
12
|
+
const debugInfoResolver = DebugInfoResolver.fromWasm(wasmBinary);
|
|
20
13
|
// Step 1: Enumerate all allocated heap objects from TLSF blocks.
|
|
21
14
|
const objects = walkBlocks(memory, rtGlobals.heapBase);
|
|
22
15
|
// Step 2: Build the full object reference graph.
|
|
23
|
-
const graph = scanReferences(memory, objects,
|
|
24
|
-
// Step 3: Discover
|
|
25
|
-
const roots = findRoots(memory, rtGlobals, objects);
|
|
16
|
+
const graph = scanReferences(memory, objects, debugInfoResolver);
|
|
17
|
+
// Step 3: Discover current roots from globals, shadow stack, and pinned objects.
|
|
18
|
+
const roots = findRoots(memory, rtGlobals, objects, debugInfoResolver.getGlobalRoots(rtGlobals.mutableI32GlobalValues));
|
|
26
19
|
// Step 4: Traverse from roots to determine the live object set.
|
|
27
20
|
const liveSet = markLive(roots, graph);
|
|
28
21
|
// Step 5: Restrict both the object list and the graph to live nodes only.
|
|
@@ -33,40 +26,21 @@ export function analyzeHeap(memory, rtGlobals, wasmBinary) {
|
|
|
33
26
|
const dominatorTree = buildDominatorTree(liveGraph, rootPtrs);
|
|
34
27
|
// Step 7: Aggregate retained sizes bottom-up on the dominator tree.
|
|
35
28
|
const retainedSizes = computeRetainedSizes(liveObjects, dominatorTree);
|
|
36
|
-
// Step 8:
|
|
37
|
-
const rootTypes = classifyRootTypes(roots, liveGraph);
|
|
38
|
-
const objectRtIds = new Map(objects.map((obj) => [obj.payloadPtr, obj.rtId]));
|
|
39
|
-
// Step 9: Materialize per-object results.
|
|
29
|
+
// Step 8: Materialize per-object results for constructor aggregation.
|
|
40
30
|
const heapObjects = liveObjects.map((obj) => ({
|
|
41
31
|
address: obj.payloadPtr,
|
|
42
32
|
classId: obj.rtId,
|
|
43
|
-
className:
|
|
33
|
+
className: debugInfoResolver.getClassName(obj.rtId),
|
|
44
34
|
shallowSize: shallowSize(obj),
|
|
45
35
|
retainedSize: retainedSizes.get(obj.payloadPtr) ?? shallowSize(obj),
|
|
46
|
-
rootType: getAssignedRootType(rootTypes, obj.payloadPtr),
|
|
47
36
|
}));
|
|
48
|
-
// Step
|
|
49
|
-
const rootsWithClassName = roots.map((root) => {
|
|
50
|
-
const className = classResolver.getClassName(objectRtIds.get(root.objectPtr) ?? -1);
|
|
51
|
-
return {
|
|
52
|
-
objectPtr: root.objectPtr,
|
|
53
|
-
className,
|
|
54
|
-
rootType: root.rootType,
|
|
55
|
-
sourceAddress: root.sourceAddress,
|
|
56
|
-
};
|
|
57
|
-
});
|
|
58
|
-
// Step 11: Compute top-level totals and the class summary view.
|
|
37
|
+
// Step 9: Compute top-level totals and constructor view.
|
|
59
38
|
const totalLiveSize = heapObjects.reduce((sum, obj) => sum + obj.shallowSize, 0);
|
|
60
39
|
const totalHeapSize = memory.byteLength - computeFirstBlock(rtGlobals.heapBase);
|
|
61
|
-
const totalFreeSize = Math.max(0, totalHeapSize - totalLiveSize);
|
|
62
40
|
return {
|
|
63
|
-
|
|
64
|
-
summary: buildSummary(heapObjects),
|
|
65
|
-
roots: rootsWithClassName,
|
|
41
|
+
constructors: buildConstructors(heapObjects),
|
|
66
42
|
totalHeapSize,
|
|
67
43
|
totalLiveSize,
|
|
68
|
-
totalFreeSize,
|
|
69
|
-
objectCount: heapObjects.length,
|
|
70
44
|
};
|
|
71
45
|
}
|
|
72
46
|
function markLive(roots, graph) {
|
|
@@ -96,71 +70,45 @@ function buildLiveGraph(liveSet, graph) {
|
|
|
96
70
|
}
|
|
97
71
|
return liveGraph;
|
|
98
72
|
}
|
|
99
|
-
function
|
|
100
|
-
|
|
101
|
-
const result = new Map();
|
|
102
|
-
const localRoots = new Set();
|
|
103
|
-
const pinnedRoots = new Set();
|
|
104
|
-
const globalRoots = new Set();
|
|
105
|
-
for (const root of roots) {
|
|
106
|
-
switch (root.rootType) {
|
|
107
|
-
case "global": {
|
|
108
|
-
globalRoots.add(root.objectPtr);
|
|
109
|
-
break;
|
|
110
|
-
}
|
|
111
|
-
case "local": {
|
|
112
|
-
localRoots.add(root.objectPtr);
|
|
113
|
-
break;
|
|
114
|
-
}
|
|
115
|
-
case "pinned": {
|
|
116
|
-
pinnedRoots.add(root.objectPtr);
|
|
117
|
-
break;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
bfsAssignRootType(pinnedRoots, graph, result, "pinned");
|
|
122
|
-
bfsAssignRootType(localRoots, graph, result, "local");
|
|
123
|
-
bfsAssignRootType(globalRoots, graph, result, "global");
|
|
124
|
-
return result;
|
|
125
|
-
}
|
|
126
|
-
function bfsAssignRootType(startPtrs, graph, result, rootType) {
|
|
127
|
-
// Walk one root category at a time and stamp every reachable node with that category.
|
|
128
|
-
const visited = new Set();
|
|
129
|
-
const workList = Array.from(startPtrs);
|
|
130
|
-
for (let index = 0; index < workList.length; index++) {
|
|
131
|
-
const ptr = workList[index];
|
|
132
|
-
if (visited.has(ptr)) {
|
|
133
|
-
continue;
|
|
134
|
-
}
|
|
135
|
-
visited.add(ptr);
|
|
136
|
-
result.set(ptr, rootType);
|
|
137
|
-
for (const child of graph.get(ptr) ?? []) {
|
|
138
|
-
if (!visited.has(child)) {
|
|
139
|
-
workList.push(child);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
function buildSummary(objects) {
|
|
145
|
-
// Summary is grouped by class name and sorted like a heap-summary view.
|
|
146
|
-
const summaryByClass = new Map();
|
|
73
|
+
function buildConstructors(objects) {
|
|
74
|
+
const constructorsByClass = new Map();
|
|
147
75
|
for (const obj of objects) {
|
|
148
|
-
let entry =
|
|
76
|
+
let entry = constructorsByClass.get(obj.className);
|
|
149
77
|
if (!entry) {
|
|
150
78
|
entry = {
|
|
151
79
|
className: obj.className,
|
|
152
|
-
classId: obj.classId,
|
|
153
80
|
count: 0,
|
|
154
81
|
totalShallowSize: 0,
|
|
155
82
|
totalRetainedSize: 0,
|
|
83
|
+
instances: [],
|
|
156
84
|
};
|
|
157
|
-
|
|
85
|
+
constructorsByClass.set(obj.className, entry);
|
|
158
86
|
}
|
|
159
87
|
entry.count++;
|
|
160
88
|
entry.totalShallowSize += obj.shallowSize;
|
|
161
89
|
entry.totalRetainedSize += obj.retainedSize;
|
|
90
|
+
entry.instances.push({
|
|
91
|
+
address: obj.address,
|
|
92
|
+
shallowSize: obj.shallowSize,
|
|
93
|
+
retainedSize: obj.retainedSize,
|
|
94
|
+
});
|
|
162
95
|
}
|
|
163
|
-
return
|
|
96
|
+
return Array.from(constructorsByClass.values(), (entry) => ({
|
|
97
|
+
className: entry.className,
|
|
98
|
+
count: entry.count,
|
|
99
|
+
totalShallowSize: entry.totalShallowSize,
|
|
100
|
+
totalRetainedSize: entry.totalRetainedSize,
|
|
101
|
+
instances: sortConstructorInstances(entry.instances),
|
|
102
|
+
})).toSorted(sortConstructors);
|
|
103
|
+
}
|
|
104
|
+
function sortConstructors(lhs, rhs) {
|
|
105
|
+
return (rhs.totalRetainedSize - lhs.totalRetainedSize ||
|
|
106
|
+
rhs.totalShallowSize - lhs.totalShallowSize ||
|
|
107
|
+
rhs.count - lhs.count ||
|
|
108
|
+
lhs.className.localeCompare(rhs.className));
|
|
109
|
+
}
|
|
110
|
+
function sortConstructorInstances(instances) {
|
|
111
|
+
return instances.toSorted((lhs, rhs) => rhs.retainedSize - lhs.retainedSize || rhs.shallowSize - lhs.shallowSize || lhs.address - rhs.address);
|
|
164
112
|
}
|
|
165
113
|
function computeFirstBlock(heapBase) {
|
|
166
114
|
// Match the AssemblyScript runtime's TLSF root and first-block alignment rules.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../../../tools/heap_analyzer/src/snapshot.ts"],"names":[],"mappings":"AAAA,oCAAoC;AACpC,sCAAsC;AAEtC,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AACpE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../../../tools/heap_analyzer/src/snapshot.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,13 +5,22 @@ export interface ObjectHeader {
|
|
|
5
5
|
payloadPtr: number;
|
|
6
6
|
gcColor: number;
|
|
7
7
|
}
|
|
8
|
-
|
|
8
|
+
/** Runtime-captured values for the globals tracked in the dump header. */
|
|
9
|
+
export interface RuntimeGlobalValues {
|
|
9
10
|
dataEnd: number;
|
|
10
11
|
heapBase: number;
|
|
11
12
|
stackPointer: number;
|
|
13
|
+
/** Serialized values of mutable i32 wasm globals in module order. */
|
|
14
|
+
mutableI32GlobalValues: number[];
|
|
15
|
+
}
|
|
16
|
+
export interface GlobalRoot {
|
|
17
|
+
name: string;
|
|
18
|
+
className: string;
|
|
19
|
+
globalIndex: number;
|
|
20
|
+
value: number;
|
|
12
21
|
}
|
|
13
22
|
export interface DumpedMemory {
|
|
14
|
-
rtGlobals:
|
|
23
|
+
rtGlobals: RuntimeGlobalValues;
|
|
15
24
|
memory: DataView;
|
|
16
25
|
}
|
|
17
26
|
export interface ClassField {
|
|
@@ -20,6 +29,13 @@ export interface ClassField {
|
|
|
20
29
|
size: number;
|
|
21
30
|
isReference: boolean;
|
|
22
31
|
}
|
|
32
|
+
export declare enum BuiltinContainerKind {
|
|
33
|
+
Array = 0,
|
|
34
|
+
StaticArray = 1,
|
|
35
|
+
MapOrSet = 2,
|
|
36
|
+
SmallTuple = 3,
|
|
37
|
+
Function = 4
|
|
38
|
+
}
|
|
23
39
|
/** Layout of a single entry in a Set or Map's entries ArrayBuffer. */
|
|
24
40
|
export interface EntryLayout {
|
|
25
41
|
/** Total byte size of one entry (stride). */
|
|
@@ -31,12 +47,16 @@ export interface ClassLayout {
|
|
|
31
47
|
rtid: number;
|
|
32
48
|
name: string;
|
|
33
49
|
base: string | null;
|
|
50
|
+
byteSize: number;
|
|
34
51
|
fields: ClassField[];
|
|
52
|
+
builtinKind?: BuiltinContainerKind;
|
|
35
53
|
templateType?: string;
|
|
36
|
-
|
|
54
|
+
templateTypeIsReference?: boolean;
|
|
37
55
|
/** For Set/Map: describes the layout of entries inside the backing ArrayBuffer. */
|
|
38
56
|
entryLayout?: EntryLayout;
|
|
39
57
|
}
|
|
58
|
+
export declare function isPointerfree(classLayout: ClassLayout): boolean;
|
|
59
|
+
export declare function getReferenceFields(classLayout: ClassLayout): ClassField[];
|
|
40
60
|
export type RootType = "global" | "local" | "pinned";
|
|
41
61
|
export interface RootInfo {
|
|
42
62
|
objectPtr: number;
|
|
@@ -50,21 +70,44 @@ export interface HeapObject {
|
|
|
50
70
|
className: string;
|
|
51
71
|
shallowSize: number;
|
|
52
72
|
retainedSize: number;
|
|
53
|
-
rootType: RootType;
|
|
54
73
|
}
|
|
55
|
-
export interface
|
|
74
|
+
export interface ConstructorInstance {
|
|
75
|
+
address: number;
|
|
76
|
+
shallowSize: number;
|
|
77
|
+
retainedSize: number;
|
|
78
|
+
}
|
|
79
|
+
export interface ConstructorEntry {
|
|
56
80
|
className: string;
|
|
57
|
-
classId: number;
|
|
58
81
|
count: number;
|
|
59
82
|
totalShallowSize: number;
|
|
60
83
|
totalRetainedSize: number;
|
|
84
|
+
instances: ConstructorInstance[];
|
|
85
|
+
}
|
|
86
|
+
export type ComparisonInstanceChangeKind = "new" | "delete";
|
|
87
|
+
export interface ComparisonInstance extends ConstructorInstance {
|
|
88
|
+
changeKind: ComparisonInstanceChangeKind;
|
|
89
|
+
}
|
|
90
|
+
export interface ConstructorComparisonEntry {
|
|
91
|
+
className: string;
|
|
92
|
+
newCount: number;
|
|
93
|
+
deletedCount: number;
|
|
94
|
+
countDelta: number;
|
|
95
|
+
allocatedSize: number;
|
|
96
|
+
freedSize: number;
|
|
97
|
+
sizeDelta: number;
|
|
98
|
+
instances: ComparisonInstance[];
|
|
61
99
|
}
|
|
62
100
|
export interface HeapSnapshot {
|
|
63
|
-
|
|
64
|
-
summary: SnapshotSummaryEntry[];
|
|
65
|
-
roots: RootInfo[];
|
|
101
|
+
constructors: ConstructorEntry[];
|
|
66
102
|
totalHeapSize: number;
|
|
67
103
|
totalLiveSize: number;
|
|
68
|
-
|
|
69
|
-
|
|
104
|
+
}
|
|
105
|
+
export interface HeapComparison {
|
|
106
|
+
beforeTotalHeapSize: number;
|
|
107
|
+
afterTotalHeapSize: number;
|
|
108
|
+
totalHeapSizeDelta: number;
|
|
109
|
+
beforeTotalLiveSize: number;
|
|
110
|
+
afterTotalLiveSize: number;
|
|
111
|
+
totalLiveSizeDelta: number;
|
|
112
|
+
constructors: ConstructorComparisonEntry[];
|
|
70
113
|
}
|
|
@@ -1,4 +1,25 @@
|
|
|
1
1
|
// Copyright (C) 2026 wasm-ecosystem
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
-
export
|
|
3
|
+
export var BuiltinContainerKind;
|
|
4
|
+
(function (BuiltinContainerKind) {
|
|
5
|
+
BuiltinContainerKind[BuiltinContainerKind["Array"] = 0] = "Array";
|
|
6
|
+
BuiltinContainerKind[BuiltinContainerKind["StaticArray"] = 1] = "StaticArray";
|
|
7
|
+
BuiltinContainerKind[BuiltinContainerKind["MapOrSet"] = 2] = "MapOrSet";
|
|
8
|
+
BuiltinContainerKind[BuiltinContainerKind["SmallTuple"] = 3] = "SmallTuple";
|
|
9
|
+
BuiltinContainerKind[BuiltinContainerKind["Function"] = 4] = "Function";
|
|
10
|
+
})(BuiltinContainerKind || (BuiltinContainerKind = {}));
|
|
11
|
+
export function isPointerfree(classLayout) {
|
|
12
|
+
if (classLayout.templateTypeIsReference === true) {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
for (const field of classLayout.fields) {
|
|
16
|
+
if (field.isReference) {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
export function getReferenceFields(classLayout) {
|
|
23
|
+
return classLayout.fields.filter((field) => field.isReference);
|
|
24
|
+
}
|
|
4
25
|
//# sourceMappingURL=types.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../tools/heap_analyzer/src/types.ts"],"names":[],"mappings":"AAAA,oCAAoC;AACpC,sCAAsC"}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../tools/heap_analyzer/src/types.ts"],"names":[],"mappings":"AAAA,oCAAoC;AACpC,sCAAsC;AAsCtC,MAAM,CAAN,IAAY,oBAMX;AAND,WAAY,oBAAoB;IAC9B,iEAAK,CAAA;IACL,6EAAW,CAAA;IACX,uEAAQ,CAAA;IACR,2EAAU,CAAA;IACV,uEAAQ,CAAA;AACV,CAAC,EANW,oBAAoB,KAApB,oBAAoB,QAM/B;AAuBD,MAAM,UAAU,aAAa,CAAC,WAAwB;IACpD,IAAI,WAAW,CAAC,uBAAuB,KAAK,IAAI,EAAE,CAAC;QACjD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,KAAK,MAAM,KAAK,IAAI,WAAW,CAAC,MAAM,EAAE,CAAC;QACvC,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;YACtB,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,WAAwB;IACzD,OAAO,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;AACjE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|