From b18b296cf87f13efbc32b0d42df16ab75ef6fd8e Mon Sep 17 00:00:00 2001 From: Eric Leese Date: Mon, 27 Jan 2020 15:57:19 +0100 Subject: [PATCH] Truncate large wasm disassembly We are running out of memory on large applications. This limits disassembly output to 1000000 lines. Bug: chromium:1003022 Change-Id: I9764d5834607f7a3a65bcd1eb98df1eaec6a2d19 Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/2022827 Reviewed-by: Benedikt Meurer Commit-Queue: Eric Leese --- front_end/third_party/wasmparser/WasmDis.js | 78 ++++--------------- .../third_party/wasmparser/WasmParser.js | 30 +++---- .../wasmparser_worker/WasmParserWorker.js | 1 + 3 files changed, 31 insertions(+), 78 deletions(-) diff --git a/front_end/third_party/wasmparser/WasmDis.js b/front_end/third_party/wasmparser/WasmDis.js index 0e0465ec0e..d15bb88e03 100644 --- a/front_end/third_party/wasmparser/WasmDis.js +++ b/front_end/third_party/wasmparser/WasmDis.js @@ -174,9 +174,9 @@ function memoryAddressToString(address, code) { defaultAlignFlags = 0; break; } - if (address.flags == defaultAlignFlags) + if (address.flags == defaultAlignFlags) // hide default flags return !address.offset ? null : `offset=${address.offset}`; - if (!address.offset) + if (!address.offset) // hide default offset return `align=${1 << address.flags}`; return `offset=${address.offset | 0} align=${1 << address.flags}`; } @@ -258,64 +258,6 @@ export class NumericNameResolver { return null; } } -class LineBuffer { - constructor() { - this._firstPart = ''; - this._secondPart = ''; - this._thirdPart = ''; - this._count = 0; - } - get length() { - switch (this._count) { - case 0: - return 0; - case 1: - return this._firstPart.length; - case 2: - return this._firstPart.length + this._secondPart.length; - default: - return this._firstPart.length + - this._secondPart.length + - this._thirdPart.length; - } - } - append(part) { - switch (this._count) { - case 0: - this._firstPart = part; - this._count = 1; - break; - case 1: - this._secondPart = part; - this._count = 2; - break; - case 2: - this._thirdPart = part; - this._count = 3; - break; - default: - this._count = 1; - this._firstPart = this._firstPart + this._secondPart + - this._thirdPart + part; - break; - } - } - finalize() { - switch (this._count) { - case 0: - return ''; - case 1: - this._count = 0; - return this._firstPart; - case 2: - this._count = 0; - return this._firstPart + this._secondPart; - default: - this._count = 0; - return this._firstPart + this._secondPart + this._thirdPart; - } - } -} export var LabelMode; (function (LabelMode) { LabelMode[LabelMode["Depth"] = 0] = "Depth"; @@ -326,7 +268,7 @@ export class WasmDisassembler { constructor() { this._lines = []; this._offsets = []; - this._buffer = new LineBuffer(); + this._buffer = ''; this._indent = null; this._indentLevel = 0; this._addOffsets = false; @@ -347,6 +289,7 @@ export class WasmDisassembler { this._initExpression = []; this._backrefLabels = null; this._labelIndex = 0; + this._maxLines = 0; } get addOffsets() { return this._addOffsets; @@ -372,13 +315,17 @@ export class WasmDisassembler { throw new Error('Cannot switch nameResolver during processing.'); this._nameResolver = resolver; } + set maxLines(value) { + this._maxLines = value; + } appendBuffer(s) { - this._buffer.append(s); + this._buffer += s; } newLine() { if (this.addOffsets) this._offsets.push(this._currentPosition); - this._lines.push(this._buffer.finalize()); + this._lines.push(this._buffer); + this._buffer = ''; } printFuncType(typeIndex) { var type = this._types[typeIndex]; @@ -740,6 +687,11 @@ export class WasmDisassembler { if (this._done) throw new Error('Invalid state: disassembly process was already finished.'); while (true) { + if (this._maxLines && this._lines.length >= this._maxLines) { + this.appendBuffer(';; -- truncated --'); + this.newLine(); + return true; + } this._currentPosition = reader.position + offsetInModule; if (!reader.read()) return false; diff --git a/front_end/third_party/wasmparser/WasmParser.js b/front_end/third_party/wasmparser/WasmParser.js index 0820825e59..de85bfea0a 100644 --- a/front_end/third_party/wasmparser/WasmParser.js +++ b/front_end/third_party/wasmparser/WasmParser.js @@ -615,6 +615,19 @@ export class Int64 { } } export class BinaryReader { + constructor() { + this._data = null; + this._pos = 0; + this._length = 0; + this._eof = false; + this.state = 0 /* INITIAL */; + this.result = null; + this.error = null; + this._sectionEntriesLeft = 0; + this._sectionId = -1 /* Unknown */; + this._sectionRange = null; + this._functionRange = null; + } get currentSection() { return this.result; // TODO remove currentSection() } @@ -630,19 +643,6 @@ export class BinaryReader { get length() { return this._length; } - constructor() { - this._data = null; - this._pos = 0; - this._length = 0; - this._eof = false; - this.state = 0 /* INITIAL */; - this.result = null; - this.error = null; - this._sectionEntriesLeft = 0; - this._sectionId = -1 /* Unknown */; - this._sectionRange = null; - this._functionRange = null; - } setData(buffer, pos, length, eof) { var posDelta = pos - this._pos; this._data = new Uint8Array(buffer); @@ -1587,7 +1587,7 @@ export class BinaryReader { return false; } brTable = []; - for (var i = 0; i <= tableCount; i++) { + for (var i = 0; i <= tableCount; i++) { // including default if (!this.hasVarIntBytes()) { this._pos = pos; return false; @@ -2197,7 +2197,7 @@ if (typeof TextDecoder !== 'undefined') { return b => utf8Decoder.decode(b); }(); } - catch (_) { } + catch (_) { /* ignore */ } } if (!bytesToString) { bytesToString = b => { diff --git a/front_end/wasmparser_worker/WasmParserWorker.js b/front_end/wasmparser_worker/WasmParserWorker.js index 8273e8b42e..e1417417af 100644 --- a/front_end/wasmparser_worker/WasmParserWorker.js +++ b/front_end/wasmparser_worker/WasmParserWorker.js @@ -51,6 +51,7 @@ self.onmessage = async function(event) { parser.setData(data, 0, data.length); const dis = new WasmDis.WasmDisassembler(); dis.addOffsets = true; + dis.maxLines = 1000000; dis.disassembleChunk(parser); const result = dis.getResult(); this.postMessage({source: result.lines.join('\n'), offsets: result.offsets});