From 313e4ed87f3b8d30d7d122f3b629ea181bd4ccc9 Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Tue, 13 Dec 2022 18:51:19 +0100 Subject: [PATCH] Wasm: fix issues with debugger --- .../debug/info/LineInfoUnpackedSequence.java | 4 ++-- .../wasm/debug/info/StepLocationsFinder.java | 17 ------------- .../wasm/debug/parser/ControlFlowParser.java | 17 +++++++++---- .../wasm/generate/WasmGenerationVisitor.java | 24 +++++++++++++++---- .../teavm/chromerdp/ChromeRDPDebugger.java | 8 +++++++ .../org/teavm/chromerdp/ChromeRDPRunner.java | 2 ++ tools/chrome-rdp/src/main/js/chrome/main.js | 20 ++++++++++++---- 7 files changed, 60 insertions(+), 32 deletions(-) diff --git a/core/src/main/java/org/teavm/backend/wasm/debug/info/LineInfoUnpackedSequence.java b/core/src/main/java/org/teavm/backend/wasm/debug/info/LineInfoUnpackedSequence.java index 800412390..8e16601b1 100644 --- a/core/src/main/java/org/teavm/backend/wasm/debug/info/LineInfoUnpackedSequence.java +++ b/core/src/main/java/org/teavm/backend/wasm/debug/info/LineInfoUnpackedSequence.java @@ -59,8 +59,8 @@ public class LineInfoUnpackedSequence { } var index = CollectionUtil.binarySearch(locations, address, InstructionLocation::address); if (index < 0) { - index = -index; + index = -index - 2; } - return Math.min(locations.size() - 1, index); + return index; } } diff --git a/core/src/main/java/org/teavm/backend/wasm/debug/info/StepLocationsFinder.java b/core/src/main/java/org/teavm/backend/wasm/debug/info/StepLocationsFinder.java index fcd449be1..6b0b9719c 100644 --- a/core/src/main/java/org/teavm/backend/wasm/debug/info/StepLocationsFinder.java +++ b/core/src/main/java/org/teavm/backend/wasm/debug/info/StepLocationsFinder.java @@ -18,14 +18,9 @@ package org.teavm.backend.wasm.debug.info; import com.carrotsearch.hppc.IntArrayDeque; import com.carrotsearch.hppc.IntHashSet; import com.carrotsearch.hppc.IntSet; -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import org.teavm.backend.wasm.debug.parser.DebugInfoParser; -import org.teavm.common.ByteArrayAsyncInputStream; import org.teavm.common.CollectionUtil; public class StepLocationsFinder { @@ -208,16 +203,4 @@ public class StepLocationsFinder { this.address = address; } } - - public static void main(String[] args) throws IOException { - var file = new File("/home/konsoletyper/prog/apache-tomcat-10.0.4/webapps/wasm/classes.wasm"); - var input = new ByteArrayAsyncInputStream(Files.readAllBytes(file.toPath())); - var parser = new DebugInfoParser(input); - input.readFully(parser::parse); - var debugInfo = parser.getDebugInfo(); - - var finder = new StepLocationsFinder(debugInfo); - finder.step("org/teavm/samples/wasi/WasiTest2.java", 9, 0x943e + debugInfo.offset(), false); - System.out.println(Arrays.toString(finder.getBreakpointAddresses())); - } } diff --git a/core/src/main/java/org/teavm/backend/wasm/debug/parser/ControlFlowParser.java b/core/src/main/java/org/teavm/backend/wasm/debug/parser/ControlFlowParser.java index 0cddf4738..9ce54ce35 100644 --- a/core/src/main/java/org/teavm/backend/wasm/debug/parser/ControlFlowParser.java +++ b/core/src/main/java/org/teavm/backend/wasm/debug/parser/ControlFlowParser.java @@ -73,6 +73,7 @@ public class ControlFlowParser implements CodeSectionListener, CodeListener, Add var token = blocks.size(); var branch = !loop ? newPendingBranch(false) : null; var block = new Block(branch, address); + block.loop = loop; blocks.add(block); if (branch != null) { block.pendingBranches.add(branch); @@ -135,17 +136,16 @@ public class ControlFlowParser implements CodeSectionListener, CodeListener, Add if (opcode == BranchOpcode.BR_IF) { pendingBranches.add(branch); } - var block = blocks.get(target); - block.pendingBranches.add(branch); + branch.jumpTo(blocks.get(target)); } @Override public void tableBranch(int[] depths, int[] targets, int defaultDepth, int defaultTarget) { var branch = newPendingBranch(false); for (var target : targets) { - blocks.get(target).pendingBranches.add(branch); + branch.jumpTo(blocks.get(target)); } - blocks.get(defaultTarget).pendingBranches.add(branch); + branch.jumpTo(blocks.get(defaultDepth)); } private Branch newPendingBranch(boolean isCall) { @@ -185,6 +185,7 @@ public class ControlFlowParser implements CodeSectionListener, CodeListener, Add private static class Block { Branch branch; + boolean loop; final int address; List pendingBranches = new ArrayList<>(); @@ -203,5 +204,13 @@ public class ControlFlowParser implements CodeSectionListener, CodeListener, Add this.address = address; this.isCall = isCall; } + + void jumpTo(Block block) { + if (block.loop) { + targets.add(block.address); + } else { + block.pendingBranches.add(this); + } + } } } diff --git a/core/src/main/java/org/teavm/backend/wasm/generate/WasmGenerationVisitor.java b/core/src/main/java/org/teavm/backend/wasm/generate/WasmGenerationVisitor.java index b0c26236c..90e975b63 100644 --- a/core/src/main/java/org/teavm/backend/wasm/generate/WasmGenerationVisitor.java +++ b/core/src/main/java/org/teavm/backend/wasm/generate/WasmGenerationVisitor.java @@ -1463,26 +1463,40 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor { WasmIntBinary binary = (WasmIntBinary) expr; if (binary.getType() == WasmIntType.INT32 && binary.getOperation() == WasmIntBinaryOperation.XOR) { if (isOne(binary.getFirst())) { - return binary.getSecond(); + var result = binary.getSecond(); + if (result.getLocation() == null && expr.getLocation() != null) { + result.setLocation(expr.getLocation()); + } + return result; } if (isOne(binary.getSecond())) { - return binary.getFirst(); + var result = binary.getFirst(); + if (result.getLocation() == null && expr.getLocation() != null) { + result.setLocation(expr.getLocation()); + } + return result; } } WasmIntBinaryOperation negatedOp = negate(binary.getOperation()); if (negatedOp != null) { - return new WasmIntBinary(binary.getType(), negatedOp, binary.getFirst(), binary.getSecond()); + var result = new WasmIntBinary(binary.getType(), negatedOp, binary.getFirst(), binary.getSecond()); + result.setLocation(expr.getLocation()); + return result; } } else if (expr instanceof WasmFloatBinary) { WasmFloatBinary binary = (WasmFloatBinary) expr; WasmFloatBinaryOperation negatedOp = negate(binary.getOperation()); if (negatedOp != null) { - return new WasmFloatBinary(binary.getType(), negatedOp, binary.getFirst(), binary.getSecond()); + var result = new WasmFloatBinary(binary.getType(), negatedOp, binary.getFirst(), binary.getSecond()); + result.setLocation(expr.getLocation()); + return result; } } - return new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.EQ, expr, new WasmInt32Constant(0)); + var result = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.EQ, expr, new WasmInt32Constant(0)); + result.setLocation(expr.getLocation()); + return result; } private static boolean isOne(WasmExpression expression) { diff --git a/tools/chrome-rdp/src/main/java/org/teavm/chromerdp/ChromeRDPDebugger.java b/tools/chrome-rdp/src/main/java/org/teavm/chromerdp/ChromeRDPDebugger.java index 080d3e4d5..3dbad3991 100644 --- a/tools/chrome-rdp/src/main/java/org/teavm/chromerdp/ChromeRDPDebugger.java +++ b/tools/chrome-rdp/src/main/java/org/teavm/chromerdp/ChromeRDPDebugger.java @@ -86,6 +86,7 @@ public class ChromeRDPDebugger extends BaseChromeRDPDebugger implements JavaScri protected void onDetach() { suspended = false; callStack = null; + } private Promise injectFunctions(int contextId) { @@ -119,6 +120,7 @@ public class ChromeRDPDebugger extends BaseChromeRDPDebugger implements JavaScri protected Promise handleMessage(Message message) throws IOException { switch (message.getMethod()) { case "TeaVM.ping": + sendPong(); return Promise.VOID; case "Debugger.paused": return firePaused(parseJson(SuspendedNotification.class, message.getParams())); @@ -130,6 +132,12 @@ public class ChromeRDPDebugger extends BaseChromeRDPDebugger implements JavaScri return Promise.VOID; } + private void sendPong() { + var message = new Message(); + message.setMethod("TeaVM.pong"); + sendMessage(message); + } + private Promise firePaused(SuspendedNotification params) { suspended = true; CallFrameDTO[] callFrameDTOs = params.getCallFrames(); diff --git a/tools/chrome-rdp/src/main/java/org/teavm/chromerdp/ChromeRDPRunner.java b/tools/chrome-rdp/src/main/java/org/teavm/chromerdp/ChromeRDPRunner.java index 217237ada..e6b842f70 100644 --- a/tools/chrome-rdp/src/main/java/org/teavm/chromerdp/ChromeRDPRunner.java +++ b/tools/chrome-rdp/src/main/java/org/teavm/chromerdp/ChromeRDPRunner.java @@ -90,6 +90,7 @@ public final class ChromeRDPRunner { @Override public void detached() { + queue.offer(() -> { }); } }; @@ -121,6 +122,7 @@ public final class ChromeRDPRunner { } }).start(); } else if (!debugger.isAttached() && wasAttached) { + System.out.println("Detached"); break; } } diff --git a/tools/chrome-rdp/src/main/js/chrome/main.js b/tools/chrome-rdp/src/main/js/chrome/main.js index 94f504426..d754d1367 100644 --- a/tools/chrome-rdp/src/main/js/chrome/main.js +++ b/tools/chrome-rdp/src/main/js/chrome/main.js @@ -45,20 +45,32 @@ class DebuggerAgent { this.sendMessage(pendingMessage); } this.pendingMessages = null; - this.pingTimeout = setInterval(() => { - this.sendMessage({ method: "TeaVM.ping" }); - }, 2000); + this.sendPing(); }; } + sendPing() { + this.sendMessage({ method: "TeaVM.ping" }); + } + + schedulePing() { + this.pingTimeout = setTimeout(() => { + this.sendPing(); + }, 2000); + } + stopPing() { if (this.pingTimeout != null) { - clearInterval(this.pingTimeout); + clearTimeout(this.pingTimeout); this.pingTimeout = null; } } receiveMessage(message) { + if (message.method === "TeaVM.pong") { + this.schedulePing(); + return; + } chrome.debugger.sendCommand(this.debuggee, message.method, message.params, response => { if (message.id) { const responseToServer = {