warpo 2.5.0-alpha-3 → 3.0.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.
Files changed (70) hide show
  1. package/asconfig.schema.json +13 -0
  2. package/dist/heap_analyzer/src/classResolver.d.ts +34 -0
  3. package/dist/heap_analyzer/src/classResolver.js +206 -0
  4. package/dist/heap_analyzer/src/classResolver.js.map +1 -0
  5. package/dist/heap_analyzer/src/constants.d.ts +21 -0
  6. package/dist/heap_analyzer/src/constants.js +30 -0
  7. package/dist/heap_analyzer/src/constants.js.map +1 -0
  8. package/dist/heap_analyzer/src/dominator.d.ts +17 -0
  9. package/dist/heap_analyzer/src/dominator.js +149 -0
  10. package/dist/heap_analyzer/src/dominator.js.map +1 -0
  11. package/dist/heap_analyzer/src/dumpReader.d.ts +2 -0
  12. package/dist/heap_analyzer/src/dumpReader.js +25 -0
  13. package/dist/heap_analyzer/src/dumpReader.js.map +1 -0
  14. package/dist/heap_analyzer/src/dwarfParser.d.ts +117 -0
  15. package/dist/heap_analyzer/src/dwarfParser.js +366 -0
  16. package/dist/heap_analyzer/src/dwarfParser.js.map +1 -0
  17. package/dist/heap_analyzer/src/referenceScanner.d.ts +11 -0
  18. package/dist/heap_analyzer/src/referenceScanner.js +143 -0
  19. package/dist/heap_analyzer/src/referenceScanner.js.map +1 -0
  20. package/dist/heap_analyzer/src/retainedSize.d.ts +9 -0
  21. package/dist/heap_analyzer/src/retainedSize.js +78 -0
  22. package/dist/heap_analyzer/src/retainedSize.js.map +1 -0
  23. package/dist/heap_analyzer/src/roots.d.ts +13 -0
  24. package/dist/heap_analyzer/src/roots.js +45 -0
  25. package/dist/heap_analyzer/src/roots.js.map +1 -0
  26. package/dist/heap_analyzer/src/snapshot.d.ts +2 -0
  27. package/dist/heap_analyzer/src/snapshot.js +170 -0
  28. package/dist/heap_analyzer/src/snapshot.js.map +1 -0
  29. package/dist/heap_analyzer/src/tlsf.d.ts +18 -0
  30. package/dist/heap_analyzer/src/tlsf.js +48 -0
  31. package/dist/heap_analyzer/src/tlsf.js.map +1 -0
  32. package/dist/heap_analyzer/src/types.d.ts +70 -0
  33. package/dist/heap_analyzer/src/types.js +4 -0
  34. package/dist/heap_analyzer/src/types.js.map +1 -0
  35. package/dist/heap_analyzer/tests/classResolver.test.d.ts +1 -0
  36. package/dist/heap_analyzer/tests/classResolver.test.js +110 -0
  37. package/dist/heap_analyzer/tests/classResolver.test.js.map +1 -0
  38. package/dist/heap_analyzer/tests/dominator.test.d.ts +1 -0
  39. package/dist/heap_analyzer/tests/dominator.test.js +438 -0
  40. package/dist/heap_analyzer/tests/dominator.test.js.map +1 -0
  41. package/dist/heap_analyzer/tests/dumpReader.test.d.ts +1 -0
  42. package/dist/heap_analyzer/tests/dumpReader.test.js +51 -0
  43. package/dist/heap_analyzer/tests/dumpReader.test.js.map +1 -0
  44. package/dist/heap_analyzer/tests/dwarfParser.test.d.ts +1 -0
  45. package/dist/heap_analyzer/tests/dwarfParser.test.js +280 -0
  46. package/dist/heap_analyzer/tests/dwarfParser.test.js.map +1 -0
  47. package/dist/heap_analyzer/tests/fixture/dwarfFixture.d.ts +2 -0
  48. package/dist/heap_analyzer/tests/fixture/dwarfFixture.js +266 -0
  49. package/dist/heap_analyzer/tests/fixture/dwarfFixture.js.map +1 -0
  50. package/dist/heap_analyzer/tests/retainedSize.test.d.ts +1 -0
  51. package/dist/heap_analyzer/tests/retainedSize.test.js +57 -0
  52. package/dist/heap_analyzer/tests/retainedSize.test.js.map +1 -0
  53. package/dist/heap_analyzer/tests/roots.test.d.ts +1 -0
  54. package/dist/heap_analyzer/tests/roots.test.js +71 -0
  55. package/dist/heap_analyzer/tests/roots.test.js.map +1 -0
  56. package/dist/heap_analyzer/tests/snapshot.test.d.ts +1 -0
  57. package/dist/heap_analyzer/tests/snapshot.test.js +102 -0
  58. package/dist/heap_analyzer/tests/snapshot.test.js.map +1 -0
  59. package/dist/heap_analyzer/tests/testHelper.d.ts +18 -0
  60. package/dist/heap_analyzer/tests/testHelper.js +68 -0
  61. package/dist/heap_analyzer/tests/testHelper.js.map +1 -0
  62. package/dist/heap_analyzer/tests/tlsf.test.d.ts +1 -0
  63. package/dist/heap_analyzer/tests/tlsf.test.js +98 -0
  64. package/dist/heap_analyzer/tests/tlsf.test.js.map +1 -0
  65. package/dist/heap_analyzer/tests/wasmExecutor.d.ts +9 -0
  66. package/dist/heap_analyzer/tests/wasmExecutor.js +49 -0
  67. package/dist/heap_analyzer/tests/wasmExecutor.js.map +1 -0
  68. package/package.json +9 -4
  69. package/types/std/index.d.ts +0 -4
  70. package/types/warpo/index.d.ts +8 -0
@@ -0,0 +1,45 @@
1
+ // Copyright (C) 2026 wasm-ecosystem
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { GC_COLOR_TRANSPARENT } from "./constants.js";
4
+ /**
5
+ * Identify GC roots that can be recovered reliably from the current dump model.
6
+ *
7
+ * Currently supported:
8
+ * - shadow stack roots
9
+ * - 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
+ */
15
+ export function findRoots(memory, rtGlobals, objects) {
16
+ const validPtrs = new Set(objects.map((obj) => obj.payloadPtr));
17
+ const roots = [];
18
+ // Shadow stack in incremental runtime contains managed object pointers.
19
+ for (let addr = rtGlobals.stackPointer; addr < rtGlobals.heapBase; addr += 4) {
20
+ if (addr + 4 > memory.byteLength) {
21
+ break;
22
+ }
23
+ const ptr = memory.getUint32(addr, true);
24
+ if (ptr !== 0 && validPtrs.has(ptr)) {
25
+ roots.push({
26
+ objectPtr: ptr,
27
+ className: "",
28
+ rootType: "local",
29
+ sourceAddress: addr,
30
+ });
31
+ }
32
+ }
33
+ for (const obj of objects) {
34
+ if (obj.gcColor === GC_COLOR_TRANSPARENT) {
35
+ roots.push({
36
+ objectPtr: obj.payloadPtr,
37
+ className: "",
38
+ rootType: "pinned",
39
+ sourceAddress: 0,
40
+ });
41
+ }
42
+ }
43
+ return roots;
44
+ }
45
+ //# sourceMappingURL=roots.js.map
@@ -0,0 +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;;;;;;;;;;GAUG;AACH,MAAM,UAAU,SAAS,CAAC,MAAgB,EAAE,SAAyB,EAAE,OAAuB;IAC5F,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,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"}
@@ -0,0 +1,2 @@
1
+ import type { HeapSnapshot, RuntimeGlobals } from "./types.js";
2
+ export declare function analyzeHeap(memory: DataView, rtGlobals: RuntimeGlobals, wasmBinary: Uint8Array | ArrayBuffer): HeapSnapshot;
@@ -0,0 +1,170 @@
1
+ // Copyright (C) 2026 wasm-ecosystem
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { AL_MASK, BLOCK_OVERHEAD, ROOT_SIZE } from "./constants.js";
4
+ import { ClassResolver } from "./classResolver.js";
5
+ import { buildDominatorTree } from "./dominator.js";
6
+ import { computeRetainedSizes, shallowSize } from "./retainedSize.js";
7
+ import { findRoots } from "./roots.js";
8
+ import { scanReferences } from "./referenceScanner.js";
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
+ export function analyzeHeap(memory, rtGlobals, wasmBinary) {
18
+ // Resolve DWARF-derived class layouts once up front for the entire pipeline.
19
+ const classResolver = ClassResolver.fromWasm(wasmBinary);
20
+ // Step 1: Enumerate all allocated heap objects from TLSF blocks.
21
+ const objects = walkBlocks(memory, rtGlobals.heapBase);
22
+ // Step 2: Build the full object reference graph.
23
+ const graph = scanReferences(memory, objects, classResolver);
24
+ // Step 3: Discover currently supported roots: shadow stack and pinned objects.
25
+ const roots = findRoots(memory, rtGlobals, objects);
26
+ // Step 4: Traverse from roots to determine the live object set.
27
+ const liveSet = markLive(roots, graph);
28
+ // Step 5: Restrict both the object list and the graph to live nodes only.
29
+ const liveObjects = objects.filter((obj) => liveSet.has(obj.payloadPtr));
30
+ const liveGraph = buildLiveGraph(liveSet, graph);
31
+ // Step 6: Build the dominator tree over the live graph only.
32
+ const rootPtrs = new Set(roots.map((root) => root.objectPtr).filter((ptr) => liveSet.has(ptr)));
33
+ const dominatorTree = buildDominatorTree(liveGraph, rootPtrs);
34
+ // Step 7: Aggregate retained sizes bottom-up on the dominator tree.
35
+ const retainedSizes = computeRetainedSizes(liveObjects, dominatorTree);
36
+ // Step 8: Propagate root categories across the live graph.
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.
40
+ const heapObjects = liveObjects.map((obj) => ({
41
+ address: obj.payloadPtr,
42
+ classId: obj.rtId,
43
+ className: classResolver.getClassName(obj.rtId),
44
+ shallowSize: shallowSize(obj),
45
+ retainedSize: retainedSizes.get(obj.payloadPtr) ?? shallowSize(obj),
46
+ rootType: getAssignedRootType(rootTypes, obj.payloadPtr),
47
+ }));
48
+ // Step 10: Enrich root records with resolved class names.
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.
59
+ const totalLiveSize = heapObjects.reduce((sum, obj) => sum + obj.shallowSize, 0);
60
+ const totalHeapSize = memory.byteLength - computeFirstBlock(rtGlobals.heapBase);
61
+ const totalFreeSize = Math.max(0, totalHeapSize - totalLiveSize);
62
+ return {
63
+ objects: heapObjects,
64
+ summary: buildSummary(heapObjects),
65
+ roots: rootsWithClassName,
66
+ totalHeapSize,
67
+ totalLiveSize,
68
+ totalFreeSize,
69
+ objectCount: heapObjects.length,
70
+ };
71
+ }
72
+ function markLive(roots, graph) {
73
+ // The workList stores payload pointers that are known reachable but not yet expanded.
74
+ const live = new Set();
75
+ const workList = Array.from(new Set(roots.map((root) => root.objectPtr)));
76
+ for (let index = 0; index < workList.length; index++) {
77
+ const ptr = workList[index];
78
+ if (live.has(ptr)) {
79
+ continue;
80
+ }
81
+ live.add(ptr);
82
+ for (const child of graph.get(ptr) ?? []) {
83
+ if (!live.has(child)) {
84
+ workList.push(child);
85
+ }
86
+ }
87
+ }
88
+ return live;
89
+ }
90
+ function buildLiveGraph(liveSet, graph) {
91
+ // Keep only the induced subgraph over live objects so dead nodes never enter
92
+ // dominator or retained-size computation.
93
+ const liveGraph = new Map();
94
+ for (const node of liveSet) {
95
+ liveGraph.set(node, (graph.get(node) ?? []).filter((child) => liveSet.has(child)));
96
+ }
97
+ return liveGraph;
98
+ }
99
+ function classifyRootTypes(roots, graph) {
100
+ // Root-type propagation is priority-based: global > local > pinned.
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();
147
+ for (const obj of objects) {
148
+ let entry = summaryByClass.get(obj.className);
149
+ if (!entry) {
150
+ entry = {
151
+ className: obj.className,
152
+ classId: obj.classId,
153
+ count: 0,
154
+ totalShallowSize: 0,
155
+ totalRetainedSize: 0,
156
+ };
157
+ summaryByClass.set(obj.className, entry);
158
+ }
159
+ entry.count++;
160
+ entry.totalShallowSize += obj.shallowSize;
161
+ entry.totalRetainedSize += obj.retainedSize;
162
+ }
163
+ return [...summaryByClass.values()].toSorted((lhs, rhs) => rhs.totalRetainedSize - lhs.totalRetainedSize);
164
+ }
165
+ function computeFirstBlock(heapBase) {
166
+ // Match the AssemblyScript runtime's TLSF root and first-block alignment rules.
167
+ const tlsfRoot = (heapBase + AL_MASK) & ~AL_MASK;
168
+ return ((tlsfRoot + ROOT_SIZE + BLOCK_OVERHEAD + AL_MASK) & ~AL_MASK) - BLOCK_OVERHEAD;
169
+ }
170
+ //# sourceMappingURL=snapshot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../../../tools/heap_analyzer/src/snapshot.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import { ObjectHeader } from "./types.js";
2
+ /**
3
+ * Walk all TLSF blocks in the heap and return parsed object headers for used blocks.
4
+ *
5
+ * Combines block walking with object header parsing in a single pass.
6
+ * Object header layout (20 bytes from block start):
7
+ * cursor + 0: mmInfo (u32) — block metadata
8
+ * cursor + 4: nextWithColor (u32) — GC list next ptr | color (2 bits)
9
+ * cursor + 8: prev (u32) — GC list prev ptr
10
+ * cursor + 12: rtId (u32) — class ID
11
+ * cursor + 16: rtSize (u32) — payload byte size
12
+ * cursor + 20: payload starts
13
+ *
14
+ * @param memory DataView of wasm linear memory (header-stripped, address 0 = offset 0)
15
+ * @param heapBase Value of __heap_base from dump metadata
16
+ * @returns Array of ObjectHeader for all used (non-free) blocks
17
+ */
18
+ export declare function walkBlocks(memory: DataView, heapBase: number): ObjectHeader[];
@@ -0,0 +1,48 @@
1
+ // Copyright (C) 2026 wasm-ecosystem
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { AL_MASK, BLOCK_OVERHEAD, ROOT_SIZE, FREE, TAGS_MASK, TOTAL_OVERHEAD, COLOR_MASK } from "./constants.js";
4
+ /**
5
+ * Walk all TLSF blocks in the heap and return parsed object headers for used blocks.
6
+ *
7
+ * Combines block walking with object header parsing in a single pass.
8
+ * Object header layout (20 bytes from block start):
9
+ * cursor + 0: mmInfo (u32) — block metadata
10
+ * cursor + 4: nextWithColor (u32) — GC list next ptr | color (2 bits)
11
+ * cursor + 8: prev (u32) — GC list prev ptr
12
+ * cursor + 12: rtId (u32) — class ID
13
+ * cursor + 16: rtSize (u32) — payload byte size
14
+ * cursor + 20: payload starts
15
+ *
16
+ * @param memory DataView of wasm linear memory (header-stripped, address 0 = offset 0)
17
+ * @param heapBase Value of __heap_base from dump metadata
18
+ * @returns Array of ObjectHeader for all used (non-free) blocks
19
+ */
20
+ export function walkBlocks(memory, heapBase) {
21
+ const tlsfRoot = (heapBase + AL_MASK) & ~AL_MASK;
22
+ // Matches AS runtime rt/tlsf.ts:
23
+ // initialize() calls addMemory(root, rootOffset + ROOT_SIZE, ...)
24
+ // addMemory() computes start = ((start + BLOCK_OVERHEAD + AL_MASK) & ~AL_MASK) - BLOCK_OVERHEAD
25
+ const firstBlock = ((tlsfRoot + ROOT_SIZE + BLOCK_OVERHEAD + AL_MASK) & ~AL_MASK) - BLOCK_OVERHEAD;
26
+ const memoryEnd = memory.byteLength;
27
+ const objects = [];
28
+ let cursor = firstBlock;
29
+ while (cursor + 4 <= memoryEnd) {
30
+ const mmInfo = memory.getUint32(cursor, true);
31
+ const blockSize = mmInfo & ~TAGS_MASK;
32
+ // Tail sentinel: size portion is 0
33
+ if (blockSize === 0) {
34
+ break;
35
+ }
36
+ const isFree = (mmInfo & FREE) !== 0;
37
+ if (!isFree) {
38
+ const gcColor = memory.getUint32(cursor + 4, true) & COLOR_MASK;
39
+ const rtId = memory.getUint32(cursor + 12, true);
40
+ const rtSize = memory.getUint32(cursor + 16, true);
41
+ const payloadPtr = cursor + TOTAL_OVERHEAD;
42
+ objects.push({ mmInfo, rtId, rtSize, payloadPtr, gcColor });
43
+ }
44
+ cursor = cursor + BLOCK_OVERHEAD + blockSize;
45
+ }
46
+ return objects;
47
+ }
48
+ //# sourceMappingURL=tlsf.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tlsf.js","sourceRoot":"","sources":["../../../tools/heap_analyzer/src/tlsf.ts"],"names":[],"mappings":"AAAA,oCAAoC;AACpC,sCAAsC;AAGtC,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEjH;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,UAAU,CAAC,MAAgB,EAAE,QAAgB;IAC3D,MAAM,QAAQ,GAAG,CAAC,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC;IACjD,iCAAiC;IACjC,oEAAoE;IACpE,kGAAkG;IAClG,MAAM,UAAU,GAAG,CAAC,CAAC,QAAQ,GAAG,SAAS,GAAG,cAAc,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,cAAc,CAAC;IACnG,MAAM,SAAS,GAAG,MAAM,CAAC,UAAU,CAAC;IAEpC,MAAM,OAAO,GAAmB,EAAE,CAAC;IACnC,IAAI,MAAM,GAAG,UAAU,CAAC;IAExB,OAAO,MAAM,GAAG,CAAC,IAAI,SAAS,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAC9C,MAAM,SAAS,GAAG,MAAM,GAAG,CAAC,SAAS,CAAC;QAEtC,mCAAmC;QACnC,IAAI,SAAS,KAAK,CAAC,EAAE,CAAC;YACpB,MAAM;QACR,CAAC;QAED,MAAM,MAAM,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;QACrC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,OAAO,GAAG,MAAM,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,IAAI,CAAC,GAAG,UAAU,CAAC;YAChE,MAAM,IAAI,GAAG,MAAM,CAAC,SAAS,CAAC,MAAM,GAAG,EAAE,EAAE,IAAI,CAAC,CAAC;YACjD,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,MAAM,GAAG,EAAE,EAAE,IAAI,CAAC,CAAC;YACnD,MAAM,UAAU,GAAG,MAAM,GAAG,cAAc,CAAC;YAE3C,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC,CAAC;QAC9D,CAAC;QAED,MAAM,GAAG,MAAM,GAAG,cAAc,GAAG,SAAS,CAAC;IAC/C,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,70 @@
1
+ export interface ObjectHeader {
2
+ mmInfo: number;
3
+ rtId: number;
4
+ rtSize: number;
5
+ payloadPtr: number;
6
+ gcColor: number;
7
+ }
8
+ export interface RuntimeGlobals {
9
+ dataEnd: number;
10
+ heapBase: number;
11
+ stackPointer: number;
12
+ }
13
+ export interface DumpedMemory {
14
+ rtGlobals: RuntimeGlobals;
15
+ memory: DataView;
16
+ }
17
+ export interface ClassField {
18
+ name: string;
19
+ offset: number;
20
+ size: number;
21
+ isReference: boolean;
22
+ }
23
+ /** Layout of a single entry in a Set or Map's entries ArrayBuffer. */
24
+ export interface EntryLayout {
25
+ /** Total byte size of one entry (stride). */
26
+ size: number;
27
+ /** Fields within the entry that are managed references. */
28
+ referenceOffsets: number[];
29
+ }
30
+ export interface ClassLayout {
31
+ rtid: number;
32
+ name: string;
33
+ base: string | null;
34
+ fields: ClassField[];
35
+ templateType?: string;
36
+ elementIsReference?: boolean;
37
+ /** For Set/Map: describes the layout of entries inside the backing ArrayBuffer. */
38
+ entryLayout?: EntryLayout;
39
+ }
40
+ export type RootType = "global" | "local" | "pinned";
41
+ export interface RootInfo {
42
+ objectPtr: number;
43
+ className: string;
44
+ rootType: RootType;
45
+ sourceAddress: number;
46
+ }
47
+ export interface HeapObject {
48
+ address: number;
49
+ classId: number;
50
+ className: string;
51
+ shallowSize: number;
52
+ retainedSize: number;
53
+ rootType: RootType;
54
+ }
55
+ export interface SnapshotSummaryEntry {
56
+ className: string;
57
+ classId: number;
58
+ count: number;
59
+ totalShallowSize: number;
60
+ totalRetainedSize: number;
61
+ }
62
+ export interface HeapSnapshot {
63
+ objects: HeapObject[];
64
+ summary: SnapshotSummaryEntry[];
65
+ roots: RootInfo[];
66
+ totalHeapSize: number;
67
+ totalLiveSize: number;
68
+ totalFreeSize: number;
69
+ objectCount: number;
70
+ }
@@ -0,0 +1,4 @@
1
+ // Copyright (C) 2026 wasm-ecosystem
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ export {};
4
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../tools/heap_analyzer/src/types.ts"],"names":[],"mappings":"AAAA,oCAAoC;AACpC,sCAAsC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,110 @@
1
+ import assert from "node:assert/strict";
2
+ import { before, describe, it } from "node:test";
3
+ import { resolveClassLayouts } from "../src/classResolver.js";
4
+ import { CLASS_PREFIX, describeIntegration } from "./testHelper.js";
5
+ describeIntegration("class-resolver", (ctx) => {
6
+ let classes;
7
+ let classMap;
8
+ before(() => {
9
+ ctx.compileFixture();
10
+ classes = resolveClassLayouts(ctx.loadFixtureWasm());
11
+ classMap = new Map(classes.map((c) => [c.name, c]));
12
+ });
13
+ it("contains user-defined classes", () => {
14
+ const userClasses = ["Vector2", "Item", "Entity", "Character", "Player", "NPC", "TreeNode", "ListNode", "KVPair"];
15
+ for (const name of userClasses) {
16
+ assert.ok(classMap.has(CLASS_PREFIX + name), `missing class ${name}`);
17
+ }
18
+ });
19
+ it("contains stdlib classes with rtid", () => {
20
+ assert.ok(classMap.has("~lib/string/String"));
21
+ assert.ok(classMap.has("~lib/arraybuffer/ArrayBuffer"));
22
+ });
23
+ it("every class has a numeric rtid", () => {
24
+ for (const cls of classes) {
25
+ assert.strictEqual(typeof cls.rtid, "number");
26
+ }
27
+ });
28
+ it("non-zero rtIds are unique", () => {
29
+ const nonZeroRtIds = classes.filter((c) => c.rtid !== 0).map((c) => c.rtid);
30
+ assert.strictEqual(new Set(nonZeroRtIds).size, nonZeroRtIds.length);
31
+ });
32
+ describe("Vector2 layout", () => {
33
+ it("has two f32 fields at correct offsets", () => {
34
+ const vec2 = classMap.get(CLASS_PREFIX + "Vector2");
35
+ assert.strictEqual(vec2.fields.length, 2);
36
+ const x = vec2.fields.find((f) => f.name === "x");
37
+ assert.strictEqual(x.offset, 0);
38
+ assert.strictEqual(x.size, 4);
39
+ assert.strictEqual(x.isReference, false);
40
+ const y = vec2.fields.find((f) => f.name === "y");
41
+ assert.strictEqual(y.offset, 4);
42
+ assert.strictEqual(y.size, 4);
43
+ assert.strictEqual(y.isReference, false);
44
+ });
45
+ });
46
+ describe("Character layout", () => {
47
+ it("has inherited fields from Entity and own fields", () => {
48
+ const character = classMap.get(CLASS_PREFIX + "Character");
49
+ const fieldNames = character.fields.map((f) => f.name);
50
+ assert.deepStrictEqual(fieldNames, ["id", "position", "name", "hp"]);
51
+ });
52
+ it("has base set to Entity", () => {
53
+ const character = classMap.get(CLASS_PREFIX + "Character");
54
+ assert.strictEqual(character.base, CLASS_PREFIX + "Entity");
55
+ });
56
+ it("name field is a reference", () => {
57
+ const character = classMap.get(CLASS_PREFIX + "Character");
58
+ const name = character.fields.find((f) => f.name === "name");
59
+ assert.strictEqual(name.isReference, true);
60
+ });
61
+ it("hp field is not a reference", () => {
62
+ const character = classMap.get(CLASS_PREFIX + "Character");
63
+ const hp = character.fields.find((f) => f.name === "hp");
64
+ assert.strictEqual(hp.isReference, false);
65
+ });
66
+ });
67
+ describe("Player layout (deep inheritance)", () => {
68
+ it("has all inherited fields from Entity→Character plus own fields", () => {
69
+ const player = classMap.get(CLASS_PREFIX + "Player");
70
+ const fieldNames = player.fields.map((f) => f.name);
71
+ assert.deepStrictEqual(fieldNames, ["id", "position", "name", "hp", "inventory", "score"]);
72
+ });
73
+ it("has base set to Character", () => {
74
+ const player = classMap.get(CLASS_PREFIX + "Player");
75
+ assert.strictEqual(player.base, CLASS_PREFIX + "Character");
76
+ });
77
+ it("inherited fields have correct offsets", () => {
78
+ const player = classMap.get(CLASS_PREFIX + "Player");
79
+ assert.strictEqual(player.fields.find((f) => f.name === "id").offset, 0);
80
+ assert.strictEqual(player.fields.find((f) => f.name === "position").offset, 4);
81
+ assert.strictEqual(player.fields.find((f) => f.name === "name").offset, 8);
82
+ assert.strictEqual(player.fields.find((f) => f.name === "hp").offset, 12);
83
+ assert.strictEqual(player.fields.find((f) => f.name === "inventory").offset, 16);
84
+ assert.strictEqual(player.fields.find((f) => f.name === "score").offset, 20);
85
+ });
86
+ });
87
+ describe("TreeNode layout", () => {
88
+ it("has self-referencing fields", () => {
89
+ const treeNode = classMap.get(CLASS_PREFIX + "TreeNode");
90
+ const left = treeNode.fields.find((f) => f.name === "left");
91
+ const right = treeNode.fields.find((f) => f.name === "right");
92
+ assert.strictEqual(left.isReference, true);
93
+ assert.strictEqual(right.isReference, true);
94
+ });
95
+ });
96
+ describe("template types", () => {
97
+ it("resolves template type for Array<Item>", () => {
98
+ const arrayItem = classes.find((c) => c.name === `~lib/array/Array<${CLASS_PREFIX}Item>`);
99
+ if (arrayItem) {
100
+ assert.notStrictEqual(arrayItem.templateType, undefined);
101
+ }
102
+ });
103
+ });
104
+ it("excludes classes without rtid", () => {
105
+ for (const cls of classes) {
106
+ assert.notStrictEqual(cls.rtid, undefined);
107
+ }
108
+ });
109
+ });
110
+ //# sourceMappingURL=classResolver.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classResolver.test.js","sourceRoot":"","sources":["../../../tools/heap_analyzer/tests/classResolver.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};