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
@@ -0,0 +1,366 @@
1
+ // Copyright (C) 2026 wasm-ecosystem
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ /**
4
+ * DWARF debug information parser for WebAssembly files.
5
+ *
6
+ * Parses DWARF4 debug sections (debug_info, debug_abbrev, debug_str) from
7
+ * wasm custom sections. Uses wasmparser to decode the wasm binary and
8
+ * extract custom sections, then performs low-level DWARF parsing on the
9
+ * raw bytes.
10
+ */
11
+ import { BinaryReader } from "wasmparser";
12
+ // ── DWARF constants ──────────────────────────────────────────────────────────
13
+ /** DWARF tag values (DW_TAG_*). */
14
+ export const DW_TAG = {
15
+ compile_unit: 0x11,
16
+ class_type: 0x02,
17
+ inheritance: 0x1c,
18
+ member: 0x0d,
19
+ base_type: 0x24,
20
+ template_type_parameter: 0x2f,
21
+ formal_parameter: 0x05,
22
+ lexical_block: 0x0b,
23
+ subprogram: 0x2e,
24
+ variable: 0x34,
25
+ };
26
+ /** DWARF attribute names (DW_AT_*). */
27
+ export const DW_AT = {
28
+ name: 0x03,
29
+ location: 0x02,
30
+ byte_size: 0x0b,
31
+ producer: 0x25,
32
+ type: 0x49,
33
+ data_member_location: 0x38,
34
+ signature: 0x69,
35
+ low_pc: 0x11,
36
+ high_pc: 0x12,
37
+ };
38
+ /** DWARF form values (DW_FORM_*). */
39
+ export const DW_FORM = {
40
+ addr: 0x01,
41
+ data4: 0x06,
42
+ string: 0x08,
43
+ strp: 0x0e,
44
+ ref4: 0x13,
45
+ };
46
+ class BufferReader {
47
+ view;
48
+ offset;
49
+ constructor(data, offset = 0) {
50
+ this.view = data instanceof Uint8Array ? new DataView(data.buffer, data.byteOffset, data.byteLength) : data;
51
+ this.offset = offset;
52
+ }
53
+ get length() {
54
+ return this.view.byteLength;
55
+ }
56
+ readUint8() {
57
+ return this.view.getUint8(this.offset++);
58
+ }
59
+ readUint16LE() {
60
+ const val = this.view.getUint16(this.offset, true);
61
+ this.offset += 2;
62
+ return val;
63
+ }
64
+ readUint32LE() {
65
+ const val = this.view.getUint32(this.offset, true);
66
+ this.offset += 4;
67
+ return val;
68
+ }
69
+ readULEB128() {
70
+ let result = 0;
71
+ let shift = 0;
72
+ let byte;
73
+ const start = this.offset;
74
+ do {
75
+ if (this.offset >= this.view.byteLength) {
76
+ throw new Error(`ULEB128 read past end of buffer at offset ${start}`);
77
+ }
78
+ byte = this.view.getUint8(this.offset++);
79
+ result |= (byte & 0x7f) << shift;
80
+ shift += 7;
81
+ } while (byte & 0x80);
82
+ return result >>> 0;
83
+ }
84
+ readString() {
85
+ let end = this.offset;
86
+ while (end < this.view.byteLength && this.view.getUint8(end) !== 0) {
87
+ end++;
88
+ }
89
+ const bytes = new Uint8Array(this.view.buffer, this.view.byteOffset + this.offset, end - this.offset);
90
+ const value = new TextDecoder().decode(bytes);
91
+ this.offset = end + 1; // skip null terminator
92
+ return value;
93
+ }
94
+ }
95
+ /**
96
+ * Extract custom sections from a wasm binary using wasmparser's BinaryReader.
97
+ * The reader validates wasm structure while iterating through sections.
98
+ */
99
+ export function extractCustomSections(wasmBinary) {
100
+ const reader = new BinaryReader();
101
+ reader.setData(wasmBinary.buffer, wasmBinary.byteOffset, wasmBinary.byteLength);
102
+ const sections = [];
103
+ let currentSectionName;
104
+ while (reader.read()) {
105
+ switch (reader.state) {
106
+ case 3 /* BinaryReaderState.BEGIN_SECTION */: {
107
+ const info = reader.result;
108
+ if (info.id === 0 /* SectionCode.Custom */ && info.name) {
109
+ currentSectionName = new TextDecoder().decode(info.name);
110
+ }
111
+ else {
112
+ currentSectionName = undefined;
113
+ reader.skipSection();
114
+ }
115
+ break;
116
+ }
117
+ case 7 /* BinaryReaderState.SECTION_RAW_DATA */: {
118
+ if (currentSectionName !== undefined) {
119
+ const rawData = reader.result;
120
+ sections.push({
121
+ name: currentSectionName,
122
+ payload: new Uint8Array(rawData),
123
+ });
124
+ currentSectionName = undefined;
125
+ }
126
+ break;
127
+ }
128
+ case -1 /* BinaryReaderState.ERROR */: {
129
+ throw new Error("Failed to parse wasm binary");
130
+ }
131
+ }
132
+ }
133
+ return sections;
134
+ }
135
+ // ── Abbreviation table parsing ───────────────────────────────────────────────
136
+ /**
137
+ * Parse a .debug_abbrev section into an abbreviation table.
138
+ */
139
+ export function parseAbbrevTable(data) {
140
+ const table = new Map();
141
+ const reader = new BufferReader(data);
142
+ while (reader.offset < reader.length) {
143
+ const code = reader.readULEB128();
144
+ if (code === 0) {
145
+ break;
146
+ }
147
+ const tag = reader.readULEB128();
148
+ const hasChildren = reader.readUint8() === 1;
149
+ const attributes = [];
150
+ for (;;) {
151
+ const name = reader.readULEB128();
152
+ const form = reader.readULEB128();
153
+ if (name === 0 && form === 0) {
154
+ break;
155
+ }
156
+ attributes.push({ name, form });
157
+ }
158
+ table.set(code, { code, tag, hasChildren, attributes });
159
+ }
160
+ return table;
161
+ }
162
+ // ── String table parsing ─────────────────────────────────────────────────────
163
+ function parseStringTable(data) {
164
+ const table = new Map();
165
+ const decoder = new TextDecoder();
166
+ let offset = 0;
167
+ while (offset < data.length) {
168
+ let end = offset;
169
+ while (end < data.length && data[end] !== 0) {
170
+ end++;
171
+ }
172
+ table.set(offset, decoder.decode(data.subarray(offset, end)));
173
+ offset = end + 1;
174
+ }
175
+ return table;
176
+ }
177
+ // ── debug_info parsing ───────────────────────────────────────────────────────
178
+ // eslint-disable-next-line sonarjs/function-return-type
179
+ function readAttributeValue(reader, form, addressSize, stringTable, cuOffset) {
180
+ switch (form) {
181
+ case DW_FORM.string: {
182
+ return reader.readString();
183
+ }
184
+ case DW_FORM.data4: {
185
+ return reader.readUint32LE();
186
+ }
187
+ case DW_FORM.strp: {
188
+ const strOffset = reader.readUint32LE();
189
+ const str = stringTable.get(strOffset);
190
+ if (str === undefined) {
191
+ throw new Error(`String not found at offset ${strOffset} in .debug_str`);
192
+ }
193
+ return str;
194
+ }
195
+ case DW_FORM.ref4: {
196
+ return cuOffset + reader.readUint32LE();
197
+ }
198
+ case DW_FORM.addr: {
199
+ if (addressSize === 4) {
200
+ return reader.readUint32LE();
201
+ }
202
+ throw new Error(`Unsupported address size: ${addressSize}`);
203
+ }
204
+ default: {
205
+ throw new Error(`Unsupported DW_FORM: 0x${form.toString(16)}`);
206
+ }
207
+ }
208
+ }
209
+ /**
210
+ * Parse all compilation units from a .debug_info section.
211
+ */
212
+ export function parseDebugInfo(infoData, abbrevTable, stringTable) {
213
+ const units = [];
214
+ const reader = new BufferReader(infoData);
215
+ while (reader.offset < reader.length) {
216
+ const unitStart = reader.offset;
217
+ const unitLength = reader.readUint32LE();
218
+ const version = reader.readUint16LE();
219
+ const abbrevOffset = reader.readUint32LE();
220
+ const addressSize = reader.readUint8();
221
+ const unitEnd = unitStart + 4 + unitLength;
222
+ const die = parseDIETree(reader, unitEnd, abbrevTable, addressSize, stringTable, unitStart);
223
+ if (die) {
224
+ units.push({
225
+ unitLength,
226
+ version,
227
+ abbrevOffset,
228
+ addressSize,
229
+ rootDIE: die,
230
+ });
231
+ }
232
+ reader.offset = unitEnd;
233
+ }
234
+ return units;
235
+ }
236
+ function parseSingleDIE(reader, abbrevTable, addressSize, stringTable, cuOffset) {
237
+ const dieOffset = reader.offset;
238
+ const code = reader.readULEB128();
239
+ if (code === 0) {
240
+ return null;
241
+ }
242
+ const abbrev = abbrevTable.get(code);
243
+ if (!abbrev) {
244
+ throw new Error(`Unknown abbreviation code ${code} at offset ${dieOffset}`);
245
+ }
246
+ const attributes = [];
247
+ for (const attr of abbrev.attributes) {
248
+ const value = readAttributeValue(reader, attr.form, addressSize, stringTable, cuOffset);
249
+ attributes.push({ name: attr.name, form: attr.form, value });
250
+ }
251
+ return {
252
+ die: { offset: dieOffset, tag: abbrev.tag, attributes, children: [] },
253
+ hasChildren: abbrev.hasChildren,
254
+ };
255
+ }
256
+ function parseChildren(reader, unitEnd, abbrevTable, addressSize, stringTable, cuOffset) {
257
+ const children = [];
258
+ while (reader.offset < unitEnd) {
259
+ const result = parseSingleDIE(reader, abbrevTable, addressSize, stringTable, cuOffset);
260
+ if (!result) {
261
+ break;
262
+ }
263
+ if (result.hasChildren) {
264
+ result.die.children = parseChildren(reader, unitEnd, abbrevTable, addressSize, stringTable, cuOffset);
265
+ }
266
+ children.push(result.die);
267
+ }
268
+ return children;
269
+ }
270
+ function parseDIETree(reader, unitEnd, abbrevTable, addressSize, stringTable, cuOffset) {
271
+ const result = parseSingleDIE(reader, abbrevTable, addressSize, stringTable, cuOffset);
272
+ if (!result) {
273
+ return null;
274
+ }
275
+ if (result.hasChildren) {
276
+ result.die.children = parseChildren(reader, unitEnd, abbrevTable, addressSize, stringTable, cuOffset);
277
+ }
278
+ return result.die;
279
+ }
280
+ // ── High-level API ───────────────────────────────────────────────────────────
281
+ /**
282
+ * Parse DWARF debug information from a WebAssembly binary.
283
+ *
284
+ * @param wasmBinary The raw wasm file content as a Uint8Array or ArrayBuffer.
285
+ * @returns Parsed DWARF info including compilation units, abbreviations, and string table.
286
+ * @throws If required DWARF sections are missing or malformed.
287
+ *
288
+ */
289
+ export function parseDwarf(wasmBinary) {
290
+ const binary = wasmBinary instanceof Uint8Array ? wasmBinary : new Uint8Array(wasmBinary);
291
+ const customSections = extractCustomSections(binary);
292
+ const debugAbbrev = customSections.find((s) => s.name === "debug_abbrev");
293
+ const debugInfo = customSections.find((s) => s.name === "debug_info");
294
+ const debugStr = customSections.find((s) => s.name === "debug_str");
295
+ if (!debugAbbrev) {
296
+ throw new Error("Missing .debug_abbrev section in wasm binary");
297
+ }
298
+ if (!debugInfo) {
299
+ throw new Error("Missing .debug_info section in wasm binary");
300
+ }
301
+ const stringTable = parseStringTable(debugStr?.payload ?? new Uint8Array(0));
302
+ const abbreviations = parseAbbrevTable(debugAbbrev.payload);
303
+ const compilationUnits = parseDebugInfo(debugInfo.payload, abbreviations, stringTable);
304
+ return { stringTable, abbreviations, compilationUnits };
305
+ }
306
+ // ── Convenience helpers ──────────────────────────────────────────────────────
307
+ /** Human-readable tag name for known DWARF tags. */
308
+ export function tagName(tag) {
309
+ for (const [name, value] of Object.entries(DW_TAG)) {
310
+ if (value === tag) {
311
+ return `DW_TAG_${name}`;
312
+ }
313
+ }
314
+ return `DW_TAG_0x${tag.toString(16)}`;
315
+ }
316
+ /** Human-readable attribute name for known DWARF attributes. */
317
+ export function attrName(attr) {
318
+ for (const [name, value] of Object.entries(DW_AT)) {
319
+ if (value === attr) {
320
+ return `DW_AT_${name}`;
321
+ }
322
+ }
323
+ return `DW_AT_0x${attr.toString(16)}`;
324
+ }
325
+ /**
326
+ * Get a named attribute value from a DIE, or undefined if not present.
327
+ */
328
+ export function getAttr(die, attrId) {
329
+ return die.attributes.find((a) => a.name === attrId);
330
+ }
331
+ /**
332
+ * Depth-first iterate all DIEs in a tree starting from root.
333
+ */
334
+ export function* walkDIEs(root) {
335
+ const stack = [root];
336
+ while (stack.length > 0) {
337
+ const die = stack.pop();
338
+ yield die;
339
+ for (let i = die.children.length - 1; i >= 0; i--) {
340
+ stack.push(die.children[i]);
341
+ }
342
+ }
343
+ }
344
+ /**
345
+ * Find all DIEs with a specific tag in the tree (depth-first).
346
+ */
347
+ export function findDIEsByTag(root, tag) {
348
+ const results = [];
349
+ for (const die of walkDIEs(root)) {
350
+ if (die.tag === tag) {
351
+ results.push(die);
352
+ }
353
+ }
354
+ return results;
355
+ }
356
+ /**
357
+ * Build a map from DIE offset to DIE for resolving DW_FORM_ref4 references.
358
+ */
359
+ export function buildOffsetMap(root) {
360
+ const map = new Map();
361
+ for (const die of walkDIEs(root)) {
362
+ map.set(die.offset, die);
363
+ }
364
+ return map;
365
+ }
366
+ //# sourceMappingURL=dwarfParser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dwarfParser.js","sourceRoot":"","sources":["../../../tools/heap_analyzer/src/dwarfParser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { ObjectHeader } from "./types.js";
2
+ import type { ClassResolver } from "./classResolver.js";
3
+ /**
4
+ * Scan object payloads to build a precise reference graph using debug info.
5
+ *
6
+ * @param memory Header-stripped DataView (wasm addr 0 = offset 0)
7
+ * @param objects Parsed object headers from parseAllObjects
8
+ * @param classResolver ClassResolver built from debug info
9
+ * @returns Adjacency list: payloadPtr → array of referenced payloadPtrs
10
+ */
11
+ export declare function scanReferences(memory: DataView, objects: ObjectHeader[], classResolver: ClassResolver): Map<number, number[]>;
@@ -0,0 +1,143 @@
1
+ // Copyright (C) 2026 wasm-ecosystem
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ function readValidPtr(memory, addr, validPtrs) {
4
+ if (addr + 4 > memory.byteLength) {
5
+ return null;
6
+ }
7
+ const ptr = memory.getUint32(addr, true);
8
+ if (ptr === 0 || !validPtrs.has(ptr)) {
9
+ return null;
10
+ }
11
+ return ptr;
12
+ }
13
+ function scanReferenceFields(memory, obj, classResolver, validPtrs, edges) {
14
+ for (const field of classResolver.getReferenceFields(obj.rtId)) {
15
+ if (field.offset + field.size > obj.rtSize) {
16
+ // Skip fields that don't fit within the object's size (could be a broken dumped memory or stale debug info)
17
+ continue;
18
+ }
19
+ const ptr = readValidPtr(memory, obj.payloadPtr + field.offset, validPtrs);
20
+ if (ptr !== null) {
21
+ edges.push(ptr);
22
+ }
23
+ }
24
+ }
25
+ function scanArrayElements(memory, obj, validPtrs, edges) {
26
+ if (obj.rtSize < 16) {
27
+ return;
28
+ }
29
+ const dataStart = memory.getUint32(obj.payloadPtr + 4, true);
30
+ const length = memory.getUint32(obj.payloadPtr + 12, true);
31
+ for (let i = 0; i < length; i++) {
32
+ const ptr = readValidPtr(memory, dataStart + i * 4, validPtrs);
33
+ if (ptr !== null) {
34
+ edges.push(ptr);
35
+ }
36
+ }
37
+ }
38
+ function scanStaticArrayElements(memory, obj, validPtrs, edges) {
39
+ const elementCount = obj.rtSize >>> 2;
40
+ for (let i = 0; i < elementCount; i++) {
41
+ const ptr = readValidPtr(memory, obj.payloadPtr + i * 4, validPtrs);
42
+ if (ptr !== null) {
43
+ edges.push(ptr);
44
+ }
45
+ }
46
+ }
47
+ function scanSetMapEntries(memory, obj, entryLayout, validPtrs, edges) {
48
+ if (entryLayout.referenceOffsets.length === 0) {
49
+ // No reference fields in entries, so we can skip scanning them entirely
50
+ return;
51
+ }
52
+ if (obj.rtSize < 20) {
53
+ // Set/Map objects should have at least 5 u32 fields in their payload.
54
+ // Hitting this means the dump is truncated/corrupted, debug info is stale,
55
+ // or the runtime layout no longer matches the hard-coded offsets below.
56
+ return;
57
+ }
58
+ const entriesPtr = memory.getUint32(obj.payloadPtr + 8, true);
59
+ const entriesOffset = memory.getInt32(obj.payloadPtr + 16, true);
60
+ if (entriesPtr === 0 || !validPtrs.has(entriesPtr)) {
61
+ return;
62
+ }
63
+ const lastReadableU32Addr = memory.byteLength - 4;
64
+ for (let i = 0; i < entriesOffset; i++) {
65
+ const entryBase = entriesPtr + i * entryLayout.size;
66
+ const taggedNextAddr = entryBase + entryLayout.size - 4;
67
+ if (taggedNextAddr > lastReadableU32Addr) {
68
+ break;
69
+ }
70
+ const taggedNext = memory.getUint32(taggedNextAddr, true);
71
+ if (taggedNext & 1) {
72
+ continue;
73
+ }
74
+ for (const refOffset of entryLayout.referenceOffsets) {
75
+ const ptr = readValidPtr(memory, entryBase + refOffset, validPtrs);
76
+ if (ptr !== null) {
77
+ edges.push(ptr);
78
+ }
79
+ }
80
+ }
81
+ }
82
+ function scanSmallTupleElements(memory, obj, validPtrs, edges) {
83
+ const bitmapSize = 8;
84
+ if (obj.rtSize <= bitmapSize) {
85
+ // An empty SmallTuple has no element slots, only the trailing bitmap.
86
+ // This also safely handles malformed dumps that are too small to contain elements.
87
+ return;
88
+ }
89
+ const elementCount = (obj.rtSize - bitmapSize) >>> 2;
90
+ const bitmapAddr = obj.payloadPtr + obj.rtSize - bitmapSize;
91
+ const bitmap = memory.getBigUint64(bitmapAddr, true);
92
+ for (let i = 0; i < elementCount; i++) {
93
+ const isRef = (bitmap & (1n << BigInt(i))) !== 0n;
94
+ if (!isRef) {
95
+ continue;
96
+ }
97
+ const ptr = readValidPtr(memory, obj.payloadPtr + i * 4, validPtrs);
98
+ if (ptr !== null) {
99
+ edges.push(ptr);
100
+ }
101
+ }
102
+ }
103
+ function scanContainerElements(memory, obj, classLayout, validPtrs, edges) {
104
+ const name = classLayout.name;
105
+ if (name.startsWith("~lib/array/Array<")) {
106
+ scanArrayElements(memory, obj, validPtrs, edges);
107
+ return;
108
+ }
109
+ if (name.startsWith("~lib/staticarray/StaticArray<")) {
110
+ scanStaticArrayElements(memory, obj, validPtrs, edges);
111
+ return;
112
+ }
113
+ if (name === "~lib/tuple/SmallTuple") {
114
+ scanSmallTupleElements(memory, obj, validPtrs, edges);
115
+ return;
116
+ }
117
+ if (classLayout.entryLayout) {
118
+ scanSetMapEntries(memory, obj, classLayout.entryLayout, validPtrs, edges);
119
+ }
120
+ }
121
+ /**
122
+ * Scan object payloads to build a precise reference graph using debug info.
123
+ *
124
+ * @param memory Header-stripped DataView (wasm addr 0 = offset 0)
125
+ * @param objects Parsed object headers from parseAllObjects
126
+ * @param classResolver ClassResolver built from debug info
127
+ * @returns Adjacency list: payloadPtr → array of referenced payloadPtrs
128
+ */
129
+ export function scanReferences(memory, objects, classResolver) {
130
+ const validPtrs = new Set(objects.map((o) => o.payloadPtr));
131
+ const graph = new Map();
132
+ for (const obj of objects) {
133
+ const edges = [];
134
+ const classLayout = classResolver.getClassDef(obj.rtId);
135
+ if (classLayout && !classResolver.isPointerfree(obj.rtId)) {
136
+ scanReferenceFields(memory, obj, classResolver, validPtrs, edges);
137
+ scanContainerElements(memory, obj, classLayout, validPtrs, edges);
138
+ }
139
+ graph.set(obj.payloadPtr, edges);
140
+ }
141
+ return graph;
142
+ }
143
+ //# sourceMappingURL=referenceScanner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"referenceScanner.js","sourceRoot":"","sources":["../../../tools/heap_analyzer/src/referenceScanner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { ObjectHeader } from "./types.js";
2
+ export declare function shallowSize(obj: ObjectHeader): number;
3
+ /**
4
+ * Compute retained sizes for the live objects represented in the dominator tree.
5
+ *
6
+ * The input objects are expected to be the live-object slice that was used to
7
+ * build the live graph and dominator tree.
8
+ */
9
+ export declare function computeRetainedSizes(objects: ObjectHeader[], dominatorTree: Map<number, number>): Map<number, number>;
@@ -0,0 +1,78 @@
1
+ // Copyright (C) 2026 wasm-ecosystem
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { BLOCK_OVERHEAD, TAGS_MASK } from "./constants.js";
4
+ import { VIRTUAL_ROOT } from "./dominator.js";
5
+ export function shallowSize(obj) {
6
+ return BLOCK_OVERHEAD + (obj.mmInfo & ~TAGS_MASK);
7
+ }
8
+ function buildChildrenMap(objects, dominatorTree) {
9
+ const objectByPtr = new Map(objects.map((obj) => [obj.payloadPtr, obj]));
10
+ const children = new Map();
11
+ for (const [node, idom] of dominatorTree) {
12
+ if (!objectByPtr.has(node)) {
13
+ throw new Error(`Missing object header for dominator-tree node ${node}`);
14
+ }
15
+ const bucket = children.get(idom);
16
+ if (bucket) {
17
+ bucket.push(node);
18
+ }
19
+ else {
20
+ children.set(idom, [node]);
21
+ }
22
+ }
23
+ return children;
24
+ }
25
+ function pushChildrenOntoStack(node, children, stack) {
26
+ const childNodes = children.get(node);
27
+ if (!childNodes) {
28
+ return;
29
+ }
30
+ for (const child of childNodes) {
31
+ stack.push({ node: child, visited: false });
32
+ }
33
+ }
34
+ function sumRetainedChildren(node, children, retained) {
35
+ const childNodes = children.get(node);
36
+ if (!childNodes) {
37
+ return 0;
38
+ }
39
+ let size = 0;
40
+ for (const child of childNodes) {
41
+ size += retained.get(child) ?? 0;
42
+ }
43
+ return size;
44
+ }
45
+ function aggregateRetainedSizes(root, objectByPtr, children) {
46
+ const retained = new Map();
47
+ const stack = [{ node: root, visited: false }];
48
+ while (stack.length > 0) {
49
+ const current = stack.pop();
50
+ if (!current.visited) {
51
+ stack.push({ node: current.node, visited: true });
52
+ pushChildrenOntoStack(current.node, children, stack);
53
+ continue;
54
+ }
55
+ if (current.node === VIRTUAL_ROOT) {
56
+ continue;
57
+ }
58
+ const obj = objectByPtr.get(current.node);
59
+ if (!obj) {
60
+ throw new Error(`Missing object header for retained-size node ${current.node}`);
61
+ }
62
+ const size = shallowSize(obj) + sumRetainedChildren(current.node, children, retained);
63
+ retained.set(current.node, size);
64
+ }
65
+ return retained;
66
+ }
67
+ /**
68
+ * Compute retained sizes for the live objects represented in the dominator tree.
69
+ *
70
+ * The input objects are expected to be the live-object slice that was used to
71
+ * build the live graph and dominator tree.
72
+ */
73
+ export function computeRetainedSizes(objects, dominatorTree) {
74
+ const objectByPtr = new Map(objects.map((obj) => [obj.payloadPtr, obj]));
75
+ const children = buildChildrenMap(objects, dominatorTree);
76
+ return aggregateRetainedSizes(VIRTUAL_ROOT, objectByPtr, children);
77
+ }
78
+ //# sourceMappingURL=retainedSize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retainedSize.js","sourceRoot":"","sources":["../../../tools/heap_analyzer/src/retainedSize.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { ObjectHeader, RootInfo, RuntimeGlobals } from "./types.js";
2
+ /**
3
+ * Identify GC roots that can be recovered reliably from the current dump model.
4
+ *
5
+ * Currently supported:
6
+ * - shadow stack roots
7
+ * - 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
+ */
13
+ export declare function findRoots(memory: DataView, rtGlobals: RuntimeGlobals, objects: ObjectHeader[]): RootInfo[];