From 847008c60e5ba3f5546ce1ea4ff3d6a8af2d7719 Mon Sep 17 00:00:00 2001 From: Chris Newland Date: Sun, 22 Oct 2017 23:33:41 +0100 Subject: [PATCH] OSR loop highlighting --- build.properties | 2 +- core/pom.xml | 2 +- .../jitwatch/core/JITWatchConstants.java | 1 + .../jitwatch/model/Compilation.java | 62 ++++++++++--- .../jitwatch/model/bytecode/LineTable.java | 79 +++++++++++++--- .../model/bytecode/MemberBytecode.java | 77 +++++++++++++--- core/src/main/resources/examples/OSRTest.java | 36 ++++++++ .../jitwatch/test/TestJarScan.java | 42 ++------- .../jitwatch/test/TestLineTable.java | 19 ++++ .../jitwatch/test/TestMemberBytecode.java | 92 +++++++++++++++++++ .../jitwatch/test/UnitTestUtil.java | 36 ++++++-- pom.xml | 2 +- ui/pom.xml | 2 +- .../jitwatch/ui/triview/ILineListener.java | 2 + .../jitwatch/ui/triview/NoOpLineListener.java | 7 +- .../jitwatch/ui/triview/TriView.java | 30 +++++- .../jitwatch/ui/triview/Viewer.java | 72 +++++++++++---- .../ui/triview/bytecode/ViewerBytecode.java | 62 ++++++++++++- .../ui/triview/source/ViewerSource.java | 4 +- 19 files changed, 525 insertions(+), 104 deletions(-) create mode 100644 core/src/main/resources/examples/OSRTest.java create mode 100644 core/src/test/java/org/adoptopenjdk/jitwatch/test/TestMemberBytecode.java diff --git a/build.properties b/build.properties index 2da9394b..e252ccc1 100644 --- a/build.properties +++ b/build.properties @@ -1 +1 @@ -version=1.2.2 +version=1.2.3 diff --git a/core/pom.xml b/core/pom.xml index a696da8d..3f3a64e2 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -4,7 +4,7 @@ com.chrisnewland jitwatch-parent - 1.2.2 + 1.2.3 jitwatch-core diff --git a/core/src/main/java/org/adoptopenjdk/jitwatch/core/JITWatchConstants.java b/core/src/main/java/org/adoptopenjdk/jitwatch/core/JITWatchConstants.java index 253c8cd2..7bc7274f 100644 --- a/core/src/main/java/org/adoptopenjdk/jitwatch/core/JITWatchConstants.java +++ b/core/src/main/java/org/adoptopenjdk/jitwatch/core/JITWatchConstants.java @@ -136,6 +136,7 @@ private JITWatchConstants() public static final String ATTR_STAMP_COMPLETED = "stamp_completed"; public static final String ATTR_NAME = "name"; public static final String ATTR_BCI = "bci"; + public static final String ATTR_OSR_BCI = "osr_bci"; public static final String ATTR_CODE = "code"; public static final String ATTR_COMPILER = "compiler"; public static final String ATTR_LEVEL = "level"; diff --git a/core/src/main/java/org/adoptopenjdk/jitwatch/model/Compilation.java b/core/src/main/java/org/adoptopenjdk/jitwatch/model/Compilation.java index 3cfb94d2..25c865d4 100644 --- a/core/src/main/java/org/adoptopenjdk/jitwatch/model/Compilation.java +++ b/core/src/main/java/org/adoptopenjdk/jitwatch/model/Compilation.java @@ -5,23 +5,25 @@ */ package org.adoptopenjdk.jitwatch.model; -import java.util.HashMap; -import java.util.Map; - -import org.adoptopenjdk.jitwatch.model.assembly.AssemblyMethod; -import org.adoptopenjdk.jitwatch.util.ParseUtil; - -import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.ATTR_COMPILE_ID; import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.ATTR_ADDRESS; -import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.ATTR_ENTRY; import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.ATTR_COMPILER; -import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.ATTR_NMSIZE; -import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.C2; +import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.ATTR_COMPILE_ID; import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.ATTR_COMPILE_KIND; +import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.ATTR_ENTRY; import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.ATTR_LEVEL; +import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.ATTR_NMSIZE; +import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.ATTR_OSR_BCI; +import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.C2; import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.C2N; +import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.OSR; import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.TAG_FAILURE; +import java.util.HashMap; +import java.util.Map; + +import org.adoptopenjdk.jitwatch.model.assembly.AssemblyMethod; +import org.adoptopenjdk.jitwatch.util.ParseUtil; + public class Compilation { private Tag tagTaskQueued; @@ -43,6 +45,10 @@ public class Compilation private long compiledStamp; private boolean isC2N; + + private boolean isOSR; + + private int osrBCI; private String nativeAddress; @@ -136,9 +142,29 @@ public void setTagTaskQueued(Tag tagTaskQueued) { this.tagTaskQueued = tagTaskQueued; - this.compileID = tagTaskQueued.getAttributes().get(ATTR_COMPILE_ID); + Map attrs = tagTaskQueued.getAttributes(); + + this.compileID = attrs.get(ATTR_COMPILE_ID); + + queuedStamp = ParseUtil.getStamp(attrs); + + String compileKind = attrs.get(ATTR_COMPILE_KIND); + String osrBCIString = attrs.get(ATTR_OSR_BCI); - queuedStamp = ParseUtil.getStamp(tagTaskQueued.getAttributes()); + if (OSR.equalsIgnoreCase(compileKind)) + { + isOSR =true; + osrBCI = -1; + + try + { + osrBCI = Integer.parseInt(osrBCIString); + } + catch (NumberFormatException nfe) + { + //logger.error("Could not parse {} '{}'", ATTR_OSR_BCI, osrBCIString); + } + } } public void setTagNMethod(Tag tagNMethod) @@ -393,4 +419,16 @@ public boolean isFailedTask() { return failedTask; } + + public boolean isOSR() + { + return isOSR; + } + + public int getOSRBCI() + { + return osrBCI; + } + + } \ No newline at end of file diff --git a/core/src/main/java/org/adoptopenjdk/jitwatch/model/bytecode/LineTable.java b/core/src/main/java/org/adoptopenjdk/jitwatch/model/bytecode/LineTable.java index 34883d43..00cae543 100644 --- a/core/src/main/java/org/adoptopenjdk/jitwatch/model/bytecode/LineTable.java +++ b/core/src/main/java/org/adoptopenjdk/jitwatch/model/bytecode/LineTable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015 Chris Newland. + * Copyright (c) 2013-2017 Chris Newland. * Licensed under https://github.com/AdoptOpenJDK/jitwatch/blob/master/LICENSE-BSD * Instructions: https://github.com/AdoptOpenJDK/jitwatch/wiki */ @@ -51,28 +51,83 @@ public void add(LineTable lineTable) public int getLastSourceLine() { - return lineTableEntries.get(lineTableEntries.size() - 1).getSourceOffset(); + return getSourceRange()[1]; } - public boolean sourceLineInRange(int sourceLine) + public int[] getSourceRange(int startBCI, int endBCI) { - boolean result = false; + boolean first = true; + + int minSourceLine = 0; + int maxSourceLine = 0; - if (lineTableEntries.size() > 0) + for (LineTableEntry entry : lineTableEntries) { - int maxIndex = lineTableEntries.size() - 1; + int entryBCI = entry.getBytecodeOffset(); + int entrySourceLine = entry.getSourceOffset(); - int minSourceLine = lineTableEntries.get(0).getSourceOffset(); - int maxSourceLine = lineTableEntries.get(maxIndex).getSourceOffset(); + if (entryBCI >= startBCI && entryBCI <= endBCI) + { + if (first) + { + minSourceLine = entrySourceLine; + maxSourceLine = entrySourceLine; + first = false; + } + else + { + minSourceLine = Math.min(entrySourceLine, minSourceLine); + maxSourceLine = Math.max(entrySourceLine, maxSourceLine); + } + } + } + + return new int[] { minSourceLine, maxSourceLine }; + } + + public int[] getSourceRange() + { + boolean first = true; - result = (sourceLine >= minSourceLine) && (sourceLine <= maxSourceLine); + int minSourceLine = 0; + int maxSourceLine = 0; - if (DEBUG_LOGGING_BYTECODE) + for (LineTableEntry entry : lineTableEntries) + { + int entrySourceLine = entry.getSourceOffset(); + + if (first) + { + minSourceLine = entrySourceLine; + maxSourceLine = entrySourceLine; + first = false; + } + else { - logger.debug("{} in range {}-{} : {}", sourceLine, minSourceLine, maxSourceLine, result); + minSourceLine = Math.min(entrySourceLine, minSourceLine); + maxSourceLine = Math.max(entrySourceLine, maxSourceLine); } } + return new int[] { minSourceLine, maxSourceLine }; + } + + public boolean sourceLineInRange(int sourceLine) + { + boolean result = false; + + int[] sourceRange = getSourceRange(); + + int minSourceLine = sourceRange[0]; + int maxSourceLine = sourceRange[1]; + + result = (sourceLine >= minSourceLine) && (sourceLine <= maxSourceLine); + + if (DEBUG_LOGGING_BYTECODE) + { + logger.debug("{} in range {}-{} : {}", sourceLine, minSourceLine, maxSourceLine, result); + } + return result; } @@ -83,7 +138,7 @@ private void sort() @Override public int compare(LineTableEntry o1, LineTableEntry o2) { - return Integer.compare(o1.getSourceOffset(), o2.getSourceOffset()); + return Integer.compare(o1.getBytecodeOffset(), o2.getBytecodeOffset()); } }); } diff --git a/core/src/main/java/org/adoptopenjdk/jitwatch/model/bytecode/MemberBytecode.java b/core/src/main/java/org/adoptopenjdk/jitwatch/model/bytecode/MemberBytecode.java index c327c0db..8163760a 100644 --- a/core/src/main/java/org/adoptopenjdk/jitwatch/model/bytecode/MemberBytecode.java +++ b/core/src/main/java/org/adoptopenjdk/jitwatch/model/bytecode/MemberBytecode.java @@ -20,17 +20,17 @@ public class MemberBytecode private List bytecodeInstructions = new ArrayList<>(); private LineTable lineTable; - + private ExceptionTable exceptionTable; private MemberSignatureParts msp; private ClassBC classBytecode; - + private int size = 0; private static final Logger logger = LoggerFactory.getLogger(MemberBytecode.class); - + private BytecodeAnnotations bytecodeAnnotations = new BytecodeAnnotations(); public MemberBytecode(ClassBC classBytecode, MemberSignatureParts msp) @@ -45,7 +45,7 @@ public ClassBC getClassBytecode() { return classBytecode; } - + public BytecodeAnnotations getBytecodeAnnotations() { return bytecodeAnnotations; @@ -59,15 +59,15 @@ public MemberSignatureParts getMemberSignatureParts() public void setInstructions(List bytecodeInstructions) { this.bytecodeInstructions = bytecodeInstructions; - + if (!bytecodeInstructions.isEmpty()) { - BytecodeInstruction instruction = bytecodeInstructions.get(bytecodeInstructions.size() -1); - + BytecodeInstruction instruction = bytecodeInstructions.get(bytecodeInstructions.size() - 1); + if (instruction != null) { int bci = instruction.getOffset(); - + size = bci + 1; } } @@ -77,17 +77,17 @@ public int size() { return size; } - + public List getInstructions() { return bytecodeInstructions; } - public BytecodeInstruction getBytecodeAtOffset(int bci) + public BytecodeInstruction getInstructionAtBCI(int bci) { if (DEBUG_LOGGING_BYTECODE) { - logger.debug("getBytecodeAtOffset({})", bci); + logger.debug("getInstructionAtBCI({})", bci); } BytecodeInstruction result = null; @@ -113,6 +113,59 @@ public BytecodeInstruction getBytecodeAtOffset(int bci) return result; } + public int findLastBackBranchToBCI(int bci) + { + if (DEBUG_LOGGING_BYTECODE) + { + logger.debug("findLastBackBranchToBCI({})", bci); + } + + int lastBackBranchBCI = -1; + + boolean inLoop = false; + + for (BytecodeInstruction instruction : bytecodeInstructions) + { + if (instruction.getOffset() == bci) + { + inLoop = true; + } + + if (inLoop) + { + Opcode opCode = instruction.getOpcode(); + + if (opCode == Opcode.GOTO || opCode == Opcode.GOTO_W) + { + List gotoParams = instruction.getParameters(); + + int paramCount = gotoParams.size(); + + if (paramCount == 1) + { + IBytecodeParam param = gotoParams.get(0); + + if (param instanceof BCParamNumeric) + { + int gotoTarget = ((BCParamNumeric) param).getValue(); + + if (gotoTarget == bci) + { + lastBackBranchBCI = instruction.getOffset(); + } + } + } + else + { + logger.error("Unexpected param count for {} {}", opCode, paramCount); + } + } + } + } + + return lastBackBranchBCI; + } + public void addLineTableEntry(LineTableEntry entry) { lineTable.add(entry); @@ -122,7 +175,7 @@ public LineTable getLineTable() { return lineTable; } - + public void addExceptionTableEntry(ExceptionTableEntry entry) { exceptionTable.add(entry); diff --git a/core/src/main/resources/examples/OSRTest.java b/core/src/main/resources/examples/OSRTest.java new file mode 100644 index 00000000..289a052e --- /dev/null +++ b/core/src/main/resources/examples/OSRTest.java @@ -0,0 +1,36 @@ +public class OSRTest +{ + public OSRTest() + { + long sum = 0; + + java.util.Random r = new java.util.Random(); + + for (int i = 0; i < 100_000; i++) + { + sum += r.nextInt(); + } + + for (int i = 0; i < 100_000; i++) + { + sum -= r.nextInt(); + } + + for (int i = 0; i < 100_000; i++) + { + sum *= r.nextInt(); + } + + for (int i = 0; i < 100_000; i++) + { + sum /= r.nextInt(); + } + + System.out.println(sum); + } + + public static void main(String[] args) + { + new OSRTest(); + } +} \ No newline at end of file diff --git a/core/src/test/java/org/adoptopenjdk/jitwatch/test/TestJarScan.java b/core/src/test/java/org/adoptopenjdk/jitwatch/test/TestJarScan.java index 80192c6e..0fec4017 100644 --- a/core/src/test/java/org/adoptopenjdk/jitwatch/test/TestJarScan.java +++ b/core/src/test/java/org/adoptopenjdk/jitwatch/test/TestJarScan.java @@ -8,13 +8,10 @@ import static org.junit.Assert.assertEquals; import java.util.Arrays; -import java.util.List; import java.util.Map; import org.adoptopenjdk.jitwatch.jarscan.sequencecount.InstructionSequence; import org.adoptopenjdk.jitwatch.jarscan.sequencecount.SequenceCountOperation; -import org.adoptopenjdk.jitwatch.loader.BytecodeLoader; -import org.adoptopenjdk.jitwatch.model.bytecode.BytecodeInstruction; import org.adoptopenjdk.jitwatch.model.bytecode.MemberBytecode; import org.adoptopenjdk.jitwatch.model.bytecode.Opcode; import org.junit.Test; @@ -23,29 +20,6 @@ public class TestJarScan { public static final boolean SHOW_OUTPUT = false; - private List getInstructions(String[] lines) - { - StringBuilder builder = new StringBuilder(); - - for (String line : lines) - { - builder.append(line).append("\n"); - } - - List instructions = BytecodeLoader.parseInstructions(builder.toString()); - - return instructions; - } - - private MemberBytecode createMemberBytecode(String[] lines) - { - MemberBytecode mbc = new MemberBytecode(null, null); - - mbc.setInstructions(getInstructions(lines)); - - return mbc; - } - @Test public void testLongBytecodeChain1() { @@ -111,7 +85,7 @@ public void testLongBytecodeChain1() "152: return" }; - MemberBytecode memberBytecode = createMemberBytecode(lines); + MemberBytecode memberBytecode = UnitTestUtil.createMemberBytecode(lines); SequenceCountOperation counter = new SequenceCountOperation(1); @@ -209,7 +183,7 @@ public void testLongBytecodeChain6() "152: return" }; - MemberBytecode memberBytecode = createMemberBytecode(lines); + MemberBytecode memberBytecode = UnitTestUtil.createMemberBytecode(lines); SequenceCountOperation counter = new SequenceCountOperation(6); @@ -289,7 +263,7 @@ public void testInfiniteLoopChain1() "8: goto 0" }; - MemberBytecode memberBytecode = createMemberBytecode(lines); + MemberBytecode memberBytecode = UnitTestUtil.createMemberBytecode(lines); SequenceCountOperation counter = new SequenceCountOperation(1); @@ -321,7 +295,7 @@ public void testInfiniteLoopChain2() "8: goto 0" }; - MemberBytecode memberBytecode = createMemberBytecode(lines); + MemberBytecode memberBytecode = UnitTestUtil.createMemberBytecode(lines); SequenceCountOperation counter = new SequenceCountOperation(2); @@ -353,7 +327,7 @@ public void testInfiniteLoopChain3() "8: goto 0" }; - MemberBytecode memberBytecode = createMemberBytecode(lines); + MemberBytecode memberBytecode = UnitTestUtil.createMemberBytecode(lines); SequenceCountOperation counter = new SequenceCountOperation(3); @@ -384,7 +358,7 @@ public void testFollowGotoChain1() "3: return " }; - MemberBytecode memberBytecode = createMemberBytecode(lines); + MemberBytecode memberBytecode = UnitTestUtil.createMemberBytecode(lines); SequenceCountOperation counter = new SequenceCountOperation(1); @@ -410,7 +384,7 @@ public void testFollowGotoChain2() "3: return " }; - MemberBytecode memberBytecode = createMemberBytecode(lines); + MemberBytecode memberBytecode = UnitTestUtil.createMemberBytecode(lines); SequenceCountOperation counter = new SequenceCountOperation(2); @@ -456,7 +430,7 @@ public void testAthrow() "43: athrow " }; - MemberBytecode memberBytecode = createMemberBytecode(lines); + MemberBytecode memberBytecode = UnitTestUtil.createMemberBytecode(lines); SequenceCountOperation counter = new SequenceCountOperation(3); diff --git a/core/src/test/java/org/adoptopenjdk/jitwatch/test/TestLineTable.java b/core/src/test/java/org/adoptopenjdk/jitwatch/test/TestLineTable.java index 10e69c19..9887cef6 100644 --- a/core/src/test/java/org/adoptopenjdk/jitwatch/test/TestLineTable.java +++ b/core/src/test/java/org/adoptopenjdk/jitwatch/test/TestLineTable.java @@ -121,4 +121,23 @@ public void testNonSequentialBCIs() assertEquals(46, table.findSourceLineForBytecodeOffset(82)); assertEquals(48, table.findSourceLineForBytecodeOffset(5000)); } + + @Test + public void testHighlightRange() + { + LineTable table = new LineTable(null); + + table.add(new LineTableEntry(8, 0)); + table.add(new LineTableEntry(9, 4)); + table.add(new LineTableEntry(12, 6)); + table.add(new LineTableEntry(12, 22)); + table.add(new LineTableEntry(14, 14)); + table.add(new LineTableEntry(17, 28)); + table.add(new LineTableEntry(18, 53)); + + int[] range = table.getSourceRange(8,25); + + assertEquals(12, range[0]); + assertEquals(14, range[1]); + } } \ No newline at end of file diff --git a/core/src/test/java/org/adoptopenjdk/jitwatch/test/TestMemberBytecode.java b/core/src/test/java/org/adoptopenjdk/jitwatch/test/TestMemberBytecode.java new file mode 100644 index 00000000..83d71abe --- /dev/null +++ b/core/src/test/java/org/adoptopenjdk/jitwatch/test/TestMemberBytecode.java @@ -0,0 +1,92 @@ +package org.adoptopenjdk.jitwatch.test; + +import static org.junit.Assert.assertEquals; + +import org.adoptopenjdk.jitwatch.model.bytecode.MemberBytecode; +import org.junit.Test; + +public class TestMemberBytecode +{ + @Test + public void testSingleBackBranch() + { + String[] lines = new String[] { + "0: iconst_0", + "1: istore_1", + "2: iload_1", + "3: bipush 100", + "5: if_icmpge 30", + "8: iload_1", + "9: iconst_2", + "10: irem", + "11: ifne 17", + "14: goto 24", + "17: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;", + "20: iload_1", + "21: invokevirtual #3 // Method java/io/PrintStream.println:(I)V", + "24: iinc 1, 1", + "27: goto 2", + "30: return" }; + + MemberBytecode memberBytecode = UnitTestUtil.createMemberBytecode(lines); + + int lastBackBranchBCI = memberBytecode.findLastBackBranchToBCI(2); + + assertEquals(27, lastBackBranchBCI); + + } + + @Test + public void testMultipleBackBranches() + { + String[] lines = new String[] { + "0: iconst_0", + "1: istore_1", + "2: iload_1", + "3: bipush 100", + "5: if_icmpge 21", + "8: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;", + "11: iload_1", + "12: invokevirtual #3 // Method java/io/PrintStream.println:(I)V", + "15: iinc 1, 1", + "18: goto 2", + "21: iconst_0", + "22: istore_1", + "23: iload_1", + "24: bipush 100", + "26: if_icmpge 42", + "29: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;", + "32: iload_1", + "33: invokevirtual #3 // Method java/io/PrintStream.println:(I)V", + "36: iinc 1, 1", + "39: goto 23", + "42: iconst_0", + "43: istore_1", + "44: iload_1", + "45: bipush 100", + "47: if_icmpge 63", + "50: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;", + "53: iload_1", + "54: invokevirtual #3 // Method java/io/PrintStream.println:(I)V", + "57: iinc 1, 1", + "60: goto 44", + "63: iconst_0", + "64: istore_1", + "65: iload_1", + "66: bipush 100", + "68: if_icmpge 84", + "71: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;", + "74: iload_1", + "75: invokevirtual #3 // Method java/io/PrintStream.println:(I)V", + "78: iinc 1, 1", + "81: goto 65", + "84: return" }; + + MemberBytecode memberBytecode = UnitTestUtil.createMemberBytecode(lines); + + assertEquals(18, memberBytecode.findLastBackBranchToBCI(2)); + assertEquals(39, memberBytecode.findLastBackBranchToBCI(23)); + assertEquals(60, memberBytecode.findLastBackBranchToBCI(44)); + assertEquals(81, memberBytecode.findLastBackBranchToBCI(65)); + } +} diff --git a/core/src/test/java/org/adoptopenjdk/jitwatch/test/UnitTestUtil.java b/core/src/test/java/org/adoptopenjdk/jitwatch/test/UnitTestUtil.java index e39d66ef..d6acbdae 100644 --- a/core/src/test/java/org/adoptopenjdk/jitwatch/test/UnitTestUtil.java +++ b/core/src/test/java/org/adoptopenjdk/jitwatch/test/UnitTestUtil.java @@ -8,13 +8,13 @@ import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.ATTR_ADDRESS; import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.ATTR_COMPILE_ID; import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_NEWLINE; +import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.TAG_NMETHOD; +import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.TAG_TASK; +import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.TAG_TASK_DONE; import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.TAG_TASK_QUEUED; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.TAG_NMETHOD; -import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.TAG_TASK; -import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.TAG_TASK_DONE; import java.lang.reflect.Constructor; import java.lang.reflect.Method; @@ -41,6 +41,7 @@ import org.adoptopenjdk.jitwatch.model.bytecode.BytecodeAnnotations; import org.adoptopenjdk.jitwatch.model.bytecode.BytecodeInstruction; import org.adoptopenjdk.jitwatch.model.bytecode.LineAnnotation; +import org.adoptopenjdk.jitwatch.model.bytecode.MemberBytecode; import org.adoptopenjdk.jitwatch.parser.ILogParseErrorListener; import org.adoptopenjdk.jitwatch.util.ClassUtil; import org.adoptopenjdk.jitwatch.util.StringUtil; @@ -56,6 +57,29 @@ public static MetaClass createMetaClassFor(JITDataModel model, String fqClassNam return model.buildAndGetMetaClass(clazz); } + public static MemberBytecode createMemberBytecode(String[] lines) + { + MemberBytecode mbc = new MemberBytecode(null, null); + + mbc.setInstructions(getInstructions(lines)); + + return mbc; + } + + private static List getInstructions(String[] lines) + { + StringBuilder builder = new StringBuilder(); + + for (String line : lines) + { + builder.append(line).append("\n"); + } + + List instructions = BytecodeLoader.parseInstructions(builder.toString()); + + return instructions; + } + public static HelperMetaMethod createTestMetaMember(String fqClassName, String methodName, Class[] params, Class returnType) { @@ -93,7 +117,7 @@ public static HelperMetaMethod createTestMetaMember(JITDataModel model, String f if (metaClass == null) { metaClass = new MetaClass(metaPackage, className); - + model.getPackageManager().addMetaClass(metaClass); } @@ -262,8 +286,8 @@ public static void processLogLines(IMetaMember member, String[] logLines) } } - public static BytecodeAnnotations buildAnnotations(boolean verifyBytecode, boolean processInlineAnnotations, IReadOnlyJITDataModel model, IMetaMember member, String[] logLines, - String[] bytecodeLines) + public static BytecodeAnnotations buildAnnotations(boolean verifyBytecode, boolean processInlineAnnotations, + IReadOnlyJITDataModel model, IMetaMember member, String[] logLines, String[] bytecodeLines) { UnitTestUtil.processLogLines(member, logLines); diff --git a/pom.xml b/pom.xml index e2ef929f..2b373f33 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ com.chrisnewland jitwatch-parent - 1.2.2 + 1.2.3 UTF-8 diff --git a/ui/pom.xml b/ui/pom.xml index 7f7e072b..ddb6ce22 100644 --- a/ui/pom.xml +++ b/ui/pom.xml @@ -4,7 +4,7 @@ com.chrisnewland jitwatch-parent - 1.2.2 + 1.2.3 jitwatch-ui diff --git a/ui/src/main/java/org/adoptopenjdk/jitwatch/ui/triview/ILineListener.java b/ui/src/main/java/org/adoptopenjdk/jitwatch/ui/triview/ILineListener.java index ae8054b3..43c30bcf 100644 --- a/ui/src/main/java/org/adoptopenjdk/jitwatch/ui/triview/ILineListener.java +++ b/ui/src/main/java/org/adoptopenjdk/jitwatch/ui/triview/ILineListener.java @@ -11,6 +11,8 @@ public enum LineType { SOURCE, BYTECODE, BYTECODE_BCI, ASSEMBLY, PLAIN } void lineHighlighted(int index, LineType lineType); + void setRange(LineType lineType, int startRange, int endRange); + void handleFocusSelf(LineType lineType); void handleFocusNext(); void handleFocusPrev(); diff --git a/ui/src/main/java/org/adoptopenjdk/jitwatch/ui/triview/NoOpLineListener.java b/ui/src/main/java/org/adoptopenjdk/jitwatch/ui/triview/NoOpLineListener.java index fc51d245..d1359a89 100644 --- a/ui/src/main/java/org/adoptopenjdk/jitwatch/ui/triview/NoOpLineListener.java +++ b/ui/src/main/java/org/adoptopenjdk/jitwatch/ui/triview/NoOpLineListener.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015 Chris Newland. + * Copyright (c) 2013-2017 Chris Newland. * Licensed under https://github.com/AdoptOpenJDK/jitwatch/blob/master/LICENSE-BSD * Instructions: https://github.com/AdoptOpenJDK/jitwatch/wiki */ @@ -26,4 +26,9 @@ public void handleFocusNext() public void handleFocusPrev() { } + + @Override + public void setRange(LineType lineType, int startRange, int endRange) + { + } } \ No newline at end of file diff --git a/ui/src/main/java/org/adoptopenjdk/jitwatch/ui/triview/TriView.java b/ui/src/main/java/org/adoptopenjdk/jitwatch/ui/triview/TriView.java index 46511e50..19c78f72 100644 --- a/ui/src/main/java/org/adoptopenjdk/jitwatch/ui/triview/TriView.java +++ b/ui/src/main/java/org/adoptopenjdk/jitwatch/ui/triview/TriView.java @@ -688,9 +688,9 @@ public void run() } private void updateBytecodeAndAssembly(boolean focusSource, int highlightBCI) - { + { Compilation compilation = currentMember.getSelectedCompilation(); - + compilationInfo.setCompilation(compilation); viewerBytecode.setContent(currentMember); @@ -856,6 +856,32 @@ public void lineHighlighted(int index, LineType lineType) } } + @Override + public void setRange(LineType lineType, int startIndex, int endIndex) + { + switch (lineType) + { + case SOURCE: + viewerSource.setStartRange(startIndex); + viewerSource.setEndRange(endIndex); + viewerSource.clearAllHighlighting(); + break; + case BYTECODE: + case BYTECODE_BCI: + viewerBytecode.setStartRange(startIndex); + viewerBytecode.setEndRange(endIndex); + viewerBytecode.clearAllHighlighting(); + break; + case ASSEMBLY: + viewerAssembly.setStartRange(startIndex); + viewerAssembly.setEndRange(endIndex); + viewerAssembly.clearAllHighlighting(); + break; + default: + break; + } + } + private void highlightFromSource(int index) { int sourceLine = index + 1; diff --git a/ui/src/main/java/org/adoptopenjdk/jitwatch/ui/triview/Viewer.java b/ui/src/main/java/org/adoptopenjdk/jitwatch/ui/triview/Viewer.java index 9c50318b..3e78a345 100644 --- a/ui/src/main/java/org/adoptopenjdk/jitwatch/ui/triview/Viewer.java +++ b/ui/src/main/java/org/adoptopenjdk/jitwatch/ui/triview/Viewer.java @@ -65,7 +65,7 @@ public class Viewer extends VBox private int scrollIndex = 0; protected int lastScrollIndex = -1; protected String originalSource; - + private double lastKnownGoodLineHeight = 15; private static final String FONT_STYLE = "-fx-font-family:" + FONT_MONOSPACE_FAMILY + "; -fx-font-size:" + FONT_MONOSPACE_SIZE @@ -75,6 +75,7 @@ public class Viewer extends VBox public static final String STYLE_HIGHLIGHTED = FONT_STYLE + "-fx-background-color:red;"; public static final String STYLE_UNHIGHLIGHTED_SUGGESTION = FONT_STYLE + "-fx-background-color:yellow;"; public static final String STYLE_SAFEPOINT = FONT_STYLE + "-fx-background-color:yellow;"; + public static final String STYLE_HIGHLIGHTED_RANGE = FONT_STYLE + "-fx-background-color:#ffdddd;"; protected Map lineAnnotations = new HashMap<>(); @@ -87,6 +88,9 @@ public class Viewer extends VBox private boolean isHighlighting; + protected int startRange = -1; + protected int endRange = -1; + public Viewer(IStageAccessProxy stageAccessProxy, boolean highlighting) { this.stageAccessProxy = stageAccessProxy; @@ -106,16 +110,48 @@ public Viewer(IStageAccessProxy stageAccessProxy, ILineListener lineListener, Li setup(); } - + + private void highlightRange() + { + if (startRange != -1 && endRange != -1) + { + for (int i = startRange; i <= endRange; i++) + { + Label label = (Label) vBoxRows.getChildren().get(i); + label.setStyle(STYLE_HIGHLIGHTED_RANGE); + } + } + } + + public int getStartRange() + { + return startRange; + } + + public void setStartRange(int startRange) + { + this.startRange = startRange; + } + + public int getEndRange() + { + return endRange; + } + + public void setEndRange(int endRange) + { + this.endRange = endRange; + } + public void clear() { lineAnnotations.clear(); - + vBoxRows.getChildren().clear(); - + lastScrollIndex = -1; } - + public LineType getLineType() { return lineType; @@ -241,11 +277,11 @@ public void handle(MouseEvent arg0) public void setContent(String inSource, boolean showLineNumbers, boolean canHighlight) { clear(); - + String source = inSource; - + isHighlighting = canHighlight; - + if (source == null) { source = "Empty"; @@ -290,7 +326,7 @@ public void setContent(List