warpo 2.5.0-alpha-2 → 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 +10 -5
  69. package/types/std/index.d.ts +0 -4
  70. package/types/warpo/index.d.ts +8 -0
@@ -49,6 +49,19 @@
49
49
  "type": "integer",
50
50
  "description": "Initial memory size for the WebAssembly module, in WebAssembly pages."
51
51
  },
52
+ "maximumMemory": {
53
+ "description": "Maximum memory limit with optional unit suffix. If smaller than one WebAssembly page, it is applied as lowMemoryLimit; otherwise it must be an exact multiple of one WebAssembly page and is converted to maximumMemory pages.",
54
+ "oneOf": [
55
+ {
56
+ "type": "integer",
57
+ "description": "Memory size in bytes."
58
+ },
59
+ {
60
+ "type": "string",
61
+ "description": "Memory size with unit suffix, e.g. 64KiB, 1MiB, 2MB, 3pages."
62
+ }
63
+ ]
64
+ },
52
65
  "stackSize": {
53
66
  "type": "integer",
54
67
  "description": "Stack size for the WebAssembly module, in bytes."
@@ -0,0 +1,34 @@
1
+ import type { ClassField, ClassLayout } from "./types.js";
2
+ /**
3
+ * Resolves class layouts from DWARF debug information embedded in a
4
+ * WebAssembly binary and provides helper queries for reference scanning.
5
+ *
6
+ * Only classes with a runtime ID (`DW_AT_signature`) are included.
7
+ */
8
+ export declare class ClassResolver {
9
+ private readonly layoutMap;
10
+ private constructor();
11
+ static fromWasm(wasmBinary: Uint8Array | ArrayBuffer): ClassResolver;
12
+ getLayouts(): ClassLayout[];
13
+ /** Returns class name, or "Class#<id>" if not found in debug info */
14
+ getClassName(classId: number): string;
15
+ /** Returns ClassDef or undefined */
16
+ getClassDef(classId: number): ClassLayout | undefined;
17
+ /**
18
+ * Check if a type has no managed references (no reference fields, no reference elements).
19
+ * Derived from field layout and elementIsReference rather than flags.
20
+ */
21
+ isPointerfree(classId: number): boolean;
22
+ /**
23
+ * Returns all reference fields (isReference == true) for this class,
24
+ * walking the full inheritance chain via base.
25
+ */
26
+ getReferenceFields(classId: number): ClassField[];
27
+ }
28
+ /**
29
+ * Resolve all class layouts from DWARF debug information embedded in a
30
+ * WebAssembly binary.
31
+ *
32
+ * Only classes with a runtime ID (`DW_AT_signature`) are included.
33
+ */
34
+ export declare function resolveClassLayouts(wasmBinary: Uint8Array | ArrayBuffer): ClassLayout[];
@@ -0,0 +1,206 @@
1
+ // Copyright (C) 2026 wasm-ecosystem
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { DW_AT, DW_TAG, buildOffsetMap, findDIEsByTag, getAttr, parseDwarf } from "./dwarfParser.js";
4
+ /**
5
+ * Resolves class layouts from DWARF debug information embedded in a
6
+ * WebAssembly binary and provides helper queries for reference scanning.
7
+ *
8
+ * Only classes with a runtime ID (`DW_AT_signature`) are included.
9
+ */
10
+ export class ClassResolver {
11
+ layoutMap;
12
+ constructor(layouts) {
13
+ this.layoutMap = new Map(layouts.map((l) => [l.rtid, l]));
14
+ }
15
+ static fromWasm(wasmBinary) {
16
+ const dwarf = parseDwarf(wasmBinary);
17
+ const classes = [];
18
+ for (const unit of dwarf.compilationUnits) {
19
+ const resolver = new CompilationUnitResolver(unit.rootDIE);
20
+ for (const layout of resolver.resolve(unit.rootDIE)) {
21
+ classes.push(layout);
22
+ }
23
+ }
24
+ flattenInheritedFields(classes);
25
+ return new ClassResolver(classes);
26
+ }
27
+ getLayouts() {
28
+ return Array.from(this.layoutMap.values());
29
+ }
30
+ /** Returns class name, or "Class#<id>" if not found in debug info */
31
+ getClassName(classId) {
32
+ const layout = this.layoutMap.get(classId);
33
+ return layout ? layout.name : `Class#${classId}`;
34
+ }
35
+ /** Returns ClassDef or undefined */
36
+ getClassDef(classId) {
37
+ return this.layoutMap.get(classId);
38
+ }
39
+ /**
40
+ * Check if a type has no managed references (no reference fields, no reference elements).
41
+ * Derived from field layout and elementIsReference rather than flags.
42
+ */
43
+ isPointerfree(classId) {
44
+ const layout = this.layoutMap.get(classId);
45
+ if (!layout) {
46
+ return false;
47
+ }
48
+ if (layout.elementIsReference === true) {
49
+ return false;
50
+ }
51
+ for (const field of layout.fields) {
52
+ if (field.isReference) {
53
+ return false;
54
+ }
55
+ }
56
+ return true;
57
+ }
58
+ /**
59
+ * Returns all reference fields (isReference == true) for this class,
60
+ * walking the full inheritance chain via base.
61
+ */
62
+ getReferenceFields(classId) {
63
+ const layout = this.layoutMap.get(classId);
64
+ if (!layout) {
65
+ return [];
66
+ }
67
+ return layout.fields.filter((f) => f.isReference);
68
+ }
69
+ }
70
+ class CompilationUnitResolver {
71
+ offsetMap;
72
+ baseTypeNames;
73
+ constructor(root) {
74
+ this.offsetMap = buildOffsetMap(root);
75
+ this.baseTypeNames = new Set();
76
+ for (const die of findDIEsByTag(root, DW_TAG.base_type)) {
77
+ const name = getAttr(die, DW_AT.name)?.value;
78
+ if (name) {
79
+ this.baseTypeNames.add(name);
80
+ }
81
+ }
82
+ }
83
+ resolve(root) {
84
+ const layouts = [];
85
+ for (const classDie of findDIEsByTag(root, DW_TAG.class_type)) {
86
+ const layout = this.resolveClassLayout(classDie);
87
+ if (layout) {
88
+ layouts.push(layout);
89
+ }
90
+ }
91
+ return layouts;
92
+ }
93
+ resolveTypeInfo(typeRef) {
94
+ const typeDie = this.offsetMap.get(typeRef);
95
+ if (!typeDie) {
96
+ return { size: 4, isReference: false };
97
+ }
98
+ const name = getAttr(typeDie, DW_AT.name)?.value;
99
+ const isReference = name === undefined ? false : !this.baseTypeNames.has(name);
100
+ const byteSize = getAttr(typeDie, DW_AT.byte_size);
101
+ const size = byteSize === undefined ? 4 : byteSize.value;
102
+ return { name, size, isReference };
103
+ }
104
+ resolveField(memberDie) {
105
+ const nameAttr = getAttr(memberDie, DW_AT.name);
106
+ const offsetAttr = getAttr(memberDie, DW_AT.data_member_location);
107
+ const typeAttr = getAttr(memberDie, DW_AT.type);
108
+ if (!nameAttr || offsetAttr === undefined || !typeAttr) {
109
+ return null;
110
+ }
111
+ const { size, isReference } = this.resolveTypeInfo(typeAttr.value);
112
+ return {
113
+ name: nameAttr.value,
114
+ offset: offsetAttr.value,
115
+ size,
116
+ isReference,
117
+ };
118
+ }
119
+ resolveTemplateType(classDie) {
120
+ const templateParam = classDie.children.find((c) => c.tag === DW_TAG.template_type_parameter);
121
+ if (!templateParam) {
122
+ return undefined;
123
+ }
124
+ const typeAttr = getAttr(templateParam, DW_AT.type);
125
+ if (!typeAttr) {
126
+ return undefined;
127
+ }
128
+ return this.resolveTypeInfo(typeAttr.value).name;
129
+ }
130
+ resolveBaseName(classDie) {
131
+ const inheritanceDie = classDie.children.find((c) => c.tag === DW_TAG.inheritance);
132
+ if (!inheritanceDie) {
133
+ return null;
134
+ }
135
+ const typeAttr = getAttr(inheritanceDie, DW_AT.type);
136
+ if (!typeAttr) {
137
+ return null;
138
+ }
139
+ const parentDie = this.offsetMap.get(typeAttr.value);
140
+ if (!parentDie) {
141
+ return null;
142
+ }
143
+ return getAttr(parentDie, DW_AT.name)?.value ?? null;
144
+ }
145
+ resolveClassLayout(classDie) {
146
+ const nameAttr = getAttr(classDie, DW_AT.name);
147
+ if (!nameAttr) {
148
+ return null;
149
+ }
150
+ const sigAttr = getAttr(classDie, DW_AT.signature);
151
+ if (sigAttr === undefined) {
152
+ return null;
153
+ }
154
+ const members = classDie.children.filter((c) => c.tag === DW_TAG.member);
155
+ const fields = [];
156
+ for (const member of members) {
157
+ const field = this.resolveField(member);
158
+ if (field) {
159
+ fields.push(field);
160
+ }
161
+ }
162
+ const layout = {
163
+ rtid: sigAttr.value,
164
+ name: nameAttr.value,
165
+ base: this.resolveBaseName(classDie),
166
+ fields,
167
+ };
168
+ const templateType = this.resolveTemplateType(classDie);
169
+ if (templateType !== undefined) {
170
+ layout.templateType = templateType;
171
+ }
172
+ return layout;
173
+ }
174
+ }
175
+ /**
176
+ * Resolve all class layouts from DWARF debug information embedded in a
177
+ * WebAssembly binary.
178
+ *
179
+ * Only classes with a runtime ID (`DW_AT_signature`) are included.
180
+ */
181
+ export function resolveClassLayouts(wasmBinary) {
182
+ return ClassResolver.fromWasm(wasmBinary).getLayouts();
183
+ }
184
+ function flattenInheritedFields(classes) {
185
+ const byName = new Map(classes.map((c) => [c.name, c]));
186
+ const flattened = new Set();
187
+ function flatten(cls) {
188
+ if (flattened.has(cls.name)) {
189
+ return;
190
+ }
191
+ flattened.add(cls.name);
192
+ if (!cls.base) {
193
+ return;
194
+ }
195
+ const parent = byName.get(cls.base);
196
+ if (!parent) {
197
+ return;
198
+ }
199
+ flatten(parent);
200
+ cls.fields = [...parent.fields, ...cls.fields];
201
+ }
202
+ for (const cls of classes) {
203
+ flatten(cls);
204
+ }
205
+ }
206
+ //# sourceMappingURL=classResolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classResolver.js","sourceRoot":"","sources":["../../../tools/heap_analyzer/src/classResolver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ export declare const AL_BITS = 4;
2
+ export declare const AL_SIZE: number;
3
+ export declare const AL_MASK: number;
4
+ export declare const BLOCK_OVERHEAD = 4;
5
+ export declare const OBJECT_OVERHEAD = 16;
6
+ export declare const TOTAL_OVERHEAD: number;
7
+ export declare const SL_BITS = 4;
8
+ export declare const SB_BITS = 8;
9
+ export declare const FL_BITS = 23;
10
+ export declare const SL_SIZE: number;
11
+ export declare const ROOT_SIZE = 1572;
12
+ export declare const FREE = 1;
13
+ export declare const LEFT_FREE = 2;
14
+ export declare const TAGS_MASK = 3;
15
+ export declare const COLOR_MASK = 3;
16
+ export declare const GC_COLOR_GRAY = 2;
17
+ export declare const GC_COLOR_TRANSPARENT = 3;
18
+ export declare const DUMP_MAGIC = 1145590593;
19
+ export declare const DUMP_MAGIC_BYTES: Uint8Array<ArrayBuffer>;
20
+ export declare const DUMP_VERSION = 1;
21
+ export declare const DUMP_HEADER_SIZE = 24;
@@ -0,0 +1,30 @@
1
+ // Copyright (C) 2026 wasm-ecosystem
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ // TLSF Allocator Constants (32-bit)
4
+ export const AL_BITS = 4;
5
+ export const AL_SIZE = 1 << AL_BITS; // 16
6
+ export const AL_MASK = AL_SIZE - 1; // 15
7
+ export const BLOCK_OVERHEAD = 4; // mmInfo only
8
+ export const OBJECT_OVERHEAD = 16; // nextWithColor + prev + rtId + rtSize
9
+ export const TOTAL_OVERHEAD = BLOCK_OVERHEAD + OBJECT_OVERHEAD; // 20
10
+ export const SL_BITS = 4;
11
+ export const SB_BITS = 8;
12
+ export const FL_BITS = 23;
13
+ export const SL_SIZE = 1 << SL_BITS; // 16
14
+ export const ROOT_SIZE = 1572; // TLSF root structure size
15
+ // Block flags (in mmInfo)
16
+ export const FREE = 1;
17
+ export const LEFT_FREE = 2;
18
+ export const TAGS_MASK = 3;
19
+ // GC Color (in nextWithColor & 3)
20
+ export const COLOR_MASK = 3;
21
+ // 0 and 1 are white/black but swap each GC cycle (white ^= 1 in rt/itcms.ts)
22
+ // Only gray (2) and transparent (3) have fixed meaning
23
+ export const GC_COLOR_GRAY = 2;
24
+ export const GC_COLOR_TRANSPARENT = 3; // pinned, always reachable
25
+ // Dump file
26
+ export const DUMP_MAGIC = 0x44485341; // "A S H D" in LE
27
+ export const DUMP_MAGIC_BYTES = new Uint8Array([0x41, 0x53, 0x48, 0x44]); // A, S, H, D
28
+ export const DUMP_VERSION = 1;
29
+ export const DUMP_HEADER_SIZE = 24;
30
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../tools/heap_analyzer/src/constants.ts"],"names":[],"mappings":"AAAA,oCAAoC;AACpC,sCAAsC;AAEtC,oCAAoC;AACpC,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,CAAC;AACzB,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,IAAI,OAAO,CAAC,CAAC,KAAK;AAC1C,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,GAAG,CAAC,CAAC,CAAC,KAAK;AAEzC,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,CAAC,cAAc;AAC/C,MAAM,CAAC,MAAM,eAAe,GAAG,EAAE,CAAC,CAAC,uCAAuC;AAC1E,MAAM,CAAC,MAAM,cAAc,GAAG,cAAc,GAAG,eAAe,CAAC,CAAC,KAAK;AAErE,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,CAAC;AACzB,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,CAAC;AACzB,MAAM,CAAC,MAAM,OAAO,GAAG,EAAE,CAAC;AAC1B,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,IAAI,OAAO,CAAC,CAAC,KAAK;AAC1C,MAAM,CAAC,MAAM,SAAS,GAAG,IAAI,CAAC,CAAC,2BAA2B;AAE1D,0BAA0B;AAC1B,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC;AACtB,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAC;AAC3B,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAC;AAE3B,kCAAkC;AAClC,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,CAAC;AAC5B,6EAA6E;AAC7E,uDAAuD;AACvD,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC;AAC/B,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,CAAC,2BAA2B;AAElE,YAAY;AACZ,MAAM,CAAC,MAAM,UAAU,GAAG,UAAU,CAAC,CAAC,kBAAkB;AACxD,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,UAAU,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,aAAa;AACvF,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC;AAC9B,MAAM,CAAC,MAAM,gBAAgB,GAAG,EAAE,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Dominator tree computation using the Lengauer-Tarjan algorithm.
3
+ * Computes immediate dominators for all nodes reachable from GC roots.
4
+ */
5
+ /**
6
+ * Virtual super-root node ID. Must not collide with any real payloadPtr.
7
+ * Using -1 (which is 0xFFFFFFFF in unsigned, impossible as a wasm address).
8
+ */
9
+ export declare const VIRTUAL_ROOT = -1;
10
+ /**
11
+ * Build dominator tree using the Lengauer-Tarjan algorithm.
12
+ *
13
+ * @param graph Adjacency list (node → successors)
14
+ * @param rootNodes Set of GC root payloadPtrs (deduplicated from RootInfo[])
15
+ * @returns Map<node, immediate dominator> for all reachable nodes
16
+ */
17
+ export declare function buildDominatorTree(graph: Map<number, number[]>, rootNodes: Set<number>): Map<number, number>;
@@ -0,0 +1,149 @@
1
+ // Copyright (C) 2026 wasm-ecosystem
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ /**
4
+ * Dominator tree computation using the Lengauer-Tarjan algorithm.
5
+ * Computes immediate dominators for all nodes reachable from GC roots.
6
+ */
7
+ /**
8
+ * Virtual super-root node ID. Must not collide with any real payloadPtr.
9
+ * Using -1 (which is 0xFFFFFFFF in unsigned, impossible as a wasm address).
10
+ */
11
+ export const VIRTUAL_ROOT = -1;
12
+ /**
13
+ * Build dominator tree using the Lengauer-Tarjan algorithm.
14
+ *
15
+ * @param graph Adjacency list (node → successors)
16
+ * @param rootNodes Set of GC root payloadPtrs (deduplicated from RootInfo[])
17
+ * @returns Map<node, immediate dominator> for all reachable nodes
18
+ */
19
+ // eslint-disable-next-line sonarjs/cognitive-complexity
20
+ export function buildDominatorTree(graph, rootNodes) {
21
+ // DFS numbering arrays
22
+ const semi = []; // semi-dominator DFS number
23
+ const vertex = []; // DFS number → node
24
+ const parent = []; // DFS number → parent DFS number
25
+ const label = []; // used for path compression (EVAL)
26
+ const ancestor = []; // union-find ancestor
27
+ const idom = []; // immediate dominator in DFS numbering
28
+ const bucket = []; // bucket[v] = list of vertices whose sdom is v
29
+ // Mapping between node IDs and DFS numbers
30
+ const nodeToNum = new Map();
31
+ let n = 0; // counter
32
+ // Build predecessor map (reverse edges) for all nodes
33
+ const pred = [];
34
+ const rootSuccessors = Array.from(rootNodes);
35
+ // Augment graph with virtual root edges
36
+ const augSuccessors = (node) => {
37
+ if (node === VIRTUAL_ROOT) {
38
+ return rootSuccessors;
39
+ }
40
+ return graph.get(node) ?? [];
41
+ };
42
+ // Step 1: DFS from VIRTUAL_ROOT
43
+ // Iterative DFS to avoid stack overflow on large graphs
44
+ const dfsStack = [{ node: VIRTUAL_ROOT, parentNum: -1 }];
45
+ while (dfsStack.length > 0) {
46
+ const { node, parentNum } = dfsStack.pop();
47
+ if (nodeToNum.has(node)) {
48
+ continue;
49
+ }
50
+ const num = n++;
51
+ nodeToNum.set(node, num);
52
+ vertex[num] = node;
53
+ parent[num] = parentNum;
54
+ semi[num] = num;
55
+ label[num] = num;
56
+ ancestor[num] = -1;
57
+ idom[num] = 0;
58
+ bucket[num] = [];
59
+ pred[num] = [];
60
+ const succs = augSuccessors(node);
61
+ // Push in reverse so we visit in forward order
62
+ for (let i = succs.length - 1; i >= 0; i--) {
63
+ const succ = succs[i];
64
+ if (!nodeToNum.has(succ)) {
65
+ // todo: to be optimized, reduce memory allocation
66
+ dfsStack.push({ node: succ, parentNum: num });
67
+ }
68
+ }
69
+ }
70
+ if (n === 0) {
71
+ return new Map();
72
+ }
73
+ // Build predecessor lists using DFS numbering
74
+ for (let u = 0; u < n; u++) {
75
+ const node = vertex[u];
76
+ const succs = augSuccessors(node);
77
+ for (const succ of succs) {
78
+ const vNum = nodeToNum.get(succ);
79
+ if (vNum !== undefined) {
80
+ pred[vNum].push(u);
81
+ }
82
+ }
83
+ }
84
+ // COMPRESS: path compression on the forest
85
+ function compress(v) {
86
+ const stack = [];
87
+ let cur = v;
88
+ while (ancestor[ancestor[cur]] !== -1) {
89
+ stack.push(cur);
90
+ cur = ancestor[cur];
91
+ }
92
+ // Now cur's ancestor is a root (ancestor[ancestor[cur]] === -1)
93
+ for (let i = stack.length - 1; i >= 0; i--) {
94
+ const u = stack[i];
95
+ if (semi[label[ancestor[u]]] < semi[label[u]]) {
96
+ label[u] = label[ancestor[u]];
97
+ }
98
+ ancestor[u] = ancestor[cur];
99
+ }
100
+ }
101
+ // EVAL: return vertex with minimum semi in ancestor chain
102
+ function evalNode(v) {
103
+ if (ancestor[v] === -1) {
104
+ return v;
105
+ }
106
+ compress(v);
107
+ return label[v];
108
+ }
109
+ // LINK: set ancestor[w] = v
110
+ function link(v, w) {
111
+ ancestor[w] = v;
112
+ }
113
+ // Step 2 & 3: Process vertices in reverse DFS order
114
+ for (let i = n - 1; i >= 1; i--) {
115
+ const w = i;
116
+ const p = parent[w];
117
+ // Step 2: Compute semi-dominator
118
+ let s = p;
119
+ for (const v of pred[w]) {
120
+ const u = evalNode(v);
121
+ if (semi[u] < s) {
122
+ s = semi[u];
123
+ }
124
+ }
125
+ semi[w] = s;
126
+ bucket[s].push(w);
127
+ link(p, w);
128
+ // Step 3: Process bucket of parent
129
+ for (const v of bucket[p]) {
130
+ const u = evalNode(v);
131
+ idom[v] = semi[u] < semi[v] ? u : p;
132
+ }
133
+ bucket[p].length = 0;
134
+ }
135
+ // Step 4: Finalize idom values
136
+ for (let i = 1; i < n; i++) {
137
+ if (idom[i] !== semi[i]) {
138
+ idom[i] = idom[idom[i]];
139
+ }
140
+ }
141
+ idom[0] = -1; // VIRTUAL_ROOT has no dominator
142
+ // Build result map: node → idom node
143
+ const result = new Map();
144
+ for (let i = 1; i < n; i++) {
145
+ result.set(vertex[i], vertex[idom[i]]);
146
+ }
147
+ return result;
148
+ }
149
+ //# sourceMappingURL=dominator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dominator.js","sourceRoot":"","sources":["../../../tools/heap_analyzer/src/dominator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { DumpedMemory } from "./types.js";
2
+ export declare function parseDumpFile(buffer: ArrayBuffer): DumpedMemory;
@@ -0,0 +1,25 @@
1
+ // Copyright (C) 2026 wasm-ecosystem
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { DUMP_MAGIC, DUMP_VERSION, DUMP_HEADER_SIZE } from "./constants.js";
4
+ export function parseDumpFile(buffer) {
5
+ if (buffer.byteLength < DUMP_HEADER_SIZE) {
6
+ throw new Error(`Dump file too small: expected at least ${DUMP_HEADER_SIZE} bytes, got ${buffer.byteLength}`);
7
+ }
8
+ const view = new DataView(buffer);
9
+ const magic = view.getUint32(0, true);
10
+ if (magic !== DUMP_MAGIC) {
11
+ throw new Error(`Invalid dump magic: expected 0x${DUMP_MAGIC.toString(16).toUpperCase()}, got 0x${magic.toString(16).toUpperCase()}`);
12
+ }
13
+ const version = view.getUint32(4, true);
14
+ if (version !== DUMP_VERSION) {
15
+ throw new Error(`Unsupported dump version: expected ${DUMP_VERSION}, got ${version}`);
16
+ }
17
+ const dataEnd = view.getUint32(8, true);
18
+ const heapBase = view.getUint32(12, true);
19
+ const stackPointer = view.getUint32(16, true);
20
+ return {
21
+ rtGlobals: { dataEnd, heapBase, stackPointer },
22
+ memory: new DataView(buffer, DUMP_HEADER_SIZE),
23
+ };
24
+ }
25
+ //# sourceMappingURL=dumpReader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dumpReader.js","sourceRoot":"","sources":["../../../tools/heap_analyzer/src/dumpReader.ts"],"names":[],"mappings":"AAAA,oCAAoC;AACpC,sCAAsC;AAEtC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAG5E,MAAM,UAAU,aAAa,CAAC,MAAmB;IAC/C,IAAI,MAAM,CAAC,UAAU,GAAG,gBAAgB,EAAE,CAAC;QACzC,MAAM,IAAI,KAAK,CAAC,0CAA0C,gBAAgB,eAAe,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC;IAChH,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC;IAElC,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IACtC,IAAI,KAAK,KAAK,UAAU,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CACb,kCAAkC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,WAAW,EAAE,WAAW,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,WAAW,EAAE,EAAE,CACrH,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IACxC,IAAI,OAAO,KAAK,YAAY,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,sCAAsC,YAAY,SAAS,OAAO,EAAE,CAAC,CAAC;IACxF,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IACxC,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IAC1C,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IAE9C,OAAO;QACL,SAAS,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE;QAC9C,MAAM,EAAE,IAAI,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;KAC/C,CAAC;AACJ,CAAC"}
@@ -0,0 +1,117 @@
1
+ /** DWARF tag values (DW_TAG_*). */
2
+ export declare const DW_TAG: {
3
+ readonly compile_unit: 17;
4
+ readonly class_type: 2;
5
+ readonly inheritance: 28;
6
+ readonly member: 13;
7
+ readonly base_type: 36;
8
+ readonly template_type_parameter: 47;
9
+ readonly formal_parameter: 5;
10
+ readonly lexical_block: 11;
11
+ readonly subprogram: 46;
12
+ readonly variable: 52;
13
+ };
14
+ /** DWARF attribute names (DW_AT_*). */
15
+ export declare const DW_AT: {
16
+ readonly name: 3;
17
+ readonly location: 2;
18
+ readonly byte_size: 11;
19
+ readonly producer: 37;
20
+ readonly type: 73;
21
+ readonly data_member_location: 56;
22
+ readonly signature: 105;
23
+ readonly low_pc: 17;
24
+ readonly high_pc: 18;
25
+ };
26
+ /** DWARF form values (DW_FORM_*). */
27
+ export declare const DW_FORM: {
28
+ readonly addr: 1;
29
+ readonly data4: 6;
30
+ readonly string: 8;
31
+ readonly strp: 14;
32
+ readonly ref4: 19;
33
+ };
34
+ export interface AbbrevAttribute {
35
+ name: number;
36
+ form: number;
37
+ }
38
+ export interface AbbrevEntry {
39
+ code: number;
40
+ tag: number;
41
+ hasChildren: boolean;
42
+ attributes: AbbrevAttribute[];
43
+ }
44
+ export type AbbrevTable = Map<number, AbbrevEntry>;
45
+ export interface DwarfAttributeValue {
46
+ name: number;
47
+ form: number;
48
+ value: string | number;
49
+ }
50
+ export interface DwarfDIE {
51
+ offset: number;
52
+ tag: number;
53
+ attributes: DwarfAttributeValue[];
54
+ children: DwarfDIE[];
55
+ }
56
+ export interface CompilationUnit {
57
+ unitLength: number;
58
+ version: number;
59
+ abbrevOffset: number;
60
+ addressSize: number;
61
+ rootDIE: DwarfDIE;
62
+ }
63
+ export interface DwarfInfo {
64
+ /** Parsed .debug_str string table (offset → string). */
65
+ stringTable: Map<number, string>;
66
+ /** Parsed abbreviation tables. */
67
+ abbreviations: AbbrevTable;
68
+ /** All compilation units in .debug_info. */
69
+ compilationUnits: CompilationUnit[];
70
+ }
71
+ interface CustomSection {
72
+ name: string;
73
+ payload: Uint8Array;
74
+ }
75
+ /**
76
+ * Extract custom sections from a wasm binary using wasmparser's BinaryReader.
77
+ * The reader validates wasm structure while iterating through sections.
78
+ */
79
+ export declare function extractCustomSections(wasmBinary: Uint8Array): CustomSection[];
80
+ /**
81
+ * Parse a .debug_abbrev section into an abbreviation table.
82
+ */
83
+ export declare function parseAbbrevTable(data: Uint8Array): AbbrevTable;
84
+ /**
85
+ * Parse all compilation units from a .debug_info section.
86
+ */
87
+ export declare function parseDebugInfo(infoData: Uint8Array, abbrevTable: AbbrevTable, stringTable: Map<number, string>): CompilationUnit[];
88
+ /**
89
+ * Parse DWARF debug information from a WebAssembly binary.
90
+ *
91
+ * @param wasmBinary The raw wasm file content as a Uint8Array or ArrayBuffer.
92
+ * @returns Parsed DWARF info including compilation units, abbreviations, and string table.
93
+ * @throws If required DWARF sections are missing or malformed.
94
+ *
95
+ */
96
+ export declare function parseDwarf(wasmBinary: Uint8Array | ArrayBuffer): DwarfInfo;
97
+ /** Human-readable tag name for known DWARF tags. */
98
+ export declare function tagName(tag: number): string;
99
+ /** Human-readable attribute name for known DWARF attributes. */
100
+ export declare function attrName(attr: number): string;
101
+ /**
102
+ * Get a named attribute value from a DIE, or undefined if not present.
103
+ */
104
+ export declare function getAttr(die: DwarfDIE, attrId: number): DwarfAttributeValue | undefined;
105
+ /**
106
+ * Depth-first iterate all DIEs in a tree starting from root.
107
+ */
108
+ export declare function walkDIEs(root: DwarfDIE): Generator<DwarfDIE>;
109
+ /**
110
+ * Find all DIEs with a specific tag in the tree (depth-first).
111
+ */
112
+ export declare function findDIEsByTag(root: DwarfDIE, tag: number): DwarfDIE[];
113
+ /**
114
+ * Build a map from DIE offset to DIE for resolving DW_FORM_ref4 references.
115
+ */
116
+ export declare function buildOffsetMap(root: DwarfDIE): Map<number, DwarfDIE>;
117
+ export {};