diff --git a/build.properties b/build.properties
index 2d48fba9..2da9394b 100644
--- a/build.properties
+++ b/build.properties
@@ -1 +1 @@
-version=1.2.1
+version=1.2.2
diff --git a/core/pom.xml b/core/pom.xml
index 0715a76a..a696da8d 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -4,7 +4,7 @@
com.chrisnewland
jitwatch-parent
- 1.2.1
+ 1.2.2
jitwatch-core
diff --git a/core/src/main/resources/examples/LoopUnroll.java b/core/src/main/resources/examples/LoopUnroll.java
new file mode 100644
index 00000000..9aef9926
--- /dev/null
+++ b/core/src/main/resources/examples/LoopUnroll.java
@@ -0,0 +1,189 @@
+
+public class LoopUnroll
+{
+ private static final int MAX = 1_000_000;
+
+ private long[] data = new long[MAX];
+
+ public LoopUnroll()
+ {
+ createData();
+
+ long total = 0;
+
+ total += constantStride1Int();
+ total += constantStride2Int();
+ total += constantStride4Int();
+ total += constantStride8Int();
+ total += constantStride16Int();
+ total += variableStrideInt(1);
+ total += constantStride1Long();
+ total += constantStride1IntWithExit();
+ total += constantStride1IntWith2Exits();
+ total += constantStride1IntWith4Exits();
+
+ System.out.println("Total: " + total);
+ }
+
+ private void createData()
+ {
+ java.util.Random random = new java.util.Random();
+
+ for (int i = 0; i < MAX; i++)
+ {
+ data[i] = random.nextLong();
+ }
+ }
+
+ private long constantStride1Int()
+ {
+ long sum = 0;
+ for (int i = 0; i < MAX; i += 1)
+ {
+ sum += data[i];
+ }
+ return sum;
+ }
+
+ private long constantStride2Int()
+ {
+ long sum = 0;
+ for (int i = 0; i < MAX; i += 2)
+ {
+ sum += data[i];
+ }
+ return sum;
+ }
+
+ private long constantStride4Int()
+ {
+ long sum = 0;
+ for (int i = 0; i < MAX; i += 4)
+ {
+ sum += data[i];
+ }
+ return sum;
+ }
+
+ private long constantStride8Int()
+ {
+ long sum = 0;
+ for (int i = 0; i < MAX; i += 8)
+ {
+ sum += data[i];
+ }
+ return sum;
+ }
+
+ private long constantStride16Int()
+ {
+ long sum = 0;
+ for (int i = 0; i < MAX; i += 16)
+ {
+ sum += data[i];
+ }
+ return sum;
+ }
+
+ private long variableStrideInt(int stride)
+ {
+ long sum = 0;
+ for (int i = 0; i < MAX; i += stride)
+ {
+ sum += data[i];
+ }
+ return sum;
+ }
+
+ private long constantStride1Long()
+ {
+ long sum = 0;
+ for (long l = 0; l < MAX; l++)
+ {
+ // cast because array index can't be longer than int
+ sum += data[(int) l];
+ }
+ return sum;
+ }
+
+ // NICE !!! unrolls with test on each unroll :)
+ private long constantStride1IntWithExit()
+ {
+ long sum = 0;
+
+ for (int i = 0; i < MAX; i += 1)
+ {
+ if (data[i] == 0x1234)
+ {
+ break;
+ }
+ else
+ {
+ sum += data[i];
+ }
+ }
+
+ return sum;
+ }
+
+ // NICE !!! unrolls with test on each unroll :)
+ private long constantStride1IntWith2Exits()
+ {
+ long sum = 0;
+
+ for (int i = 0; i < MAX; i += 1)
+ {
+ if (data[i] == 0x1234)
+ {
+ break;
+ }
+ else if (data[i] == 0x5678)
+ {
+ break;
+ }
+ else
+ {
+ sum += data[i];
+ }
+ }
+
+ return sum;
+ }
+
+ // NICE !!! unrolls with test on each unroll :)
+ private long constantStride1IntWith4Exits()
+ {
+ long sum = 0;
+
+ for (int i = 0; i < MAX; i += 1)
+ {
+ if (data[i] == 0x1234)
+ {
+ break;
+ }
+ else if (data[i] == 0x5678)
+ {
+ break;
+ }
+ else if (data[i] == 0x9ABC)
+ {
+ break;
+ }
+ else if (data[i] == 0xDEF0)
+ {
+ break;
+ }
+ else
+ {
+ sum += data[i];
+ }
+ }
+
+ return sum;
+ }
+
+ public static void main(String[] args)
+ {
+ new LoopUnroll();
+ }
+}
diff --git a/pom.xml b/pom.xml
index eb5734c8..e2ef929f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,7 +3,7 @@
com.chrisnewland
jitwatch-parent
- 1.2.1
+ 1.2.2
UTF-8
diff --git a/ui/pom.xml b/ui/pom.xml
index e4c12103..7f7e072b 100644
--- a/ui/pom.xml
+++ b/ui/pom.xml
@@ -4,7 +4,7 @@
com.chrisnewland
jitwatch-parent
- 1.2.1
+ 1.2.2
jitwatch-ui
diff --git a/ui/src/main/java/org/adoptopenjdk/jitwatch/ui/compilechain/CompileChainStage.java b/ui/src/main/java/org/adoptopenjdk/jitwatch/ui/compilechain/CompileChainStage.java
index 3501e674..e7da7819 100644
--- a/ui/src/main/java/org/adoptopenjdk/jitwatch/ui/compilechain/CompileChainStage.java
+++ b/ui/src/main/java/org/adoptopenjdk/jitwatch/ui/compilechain/CompileChainStage.java
@@ -23,10 +23,14 @@
import javafx.event.EventHandler;
import javafx.scene.Scene;
+import javafx.scene.control.Button;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.Tooltip;
import javafx.scene.input.MouseEvent;
+import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
+import javafx.scene.layout.Priority;
+import javafx.scene.layout.Region;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
@@ -80,12 +84,24 @@ public CompileChainStage(IMemberSelectedListener selectionListener, final IStage
scrollPane.setContent(pane);
compilationChooser = new CompilationChooser(selectionListener);
-
+
VBox verticalLayout = new VBox();
-
- verticalLayout.getChildren().addAll(compilationChooser.getCombo(), scrollPane);
-
+
Scene scene = UserInterfaceUtil.getScene(verticalLayout, JITWatchUI.WINDOW_WIDTH, JITWatchUI.WINDOW_HEIGHT);
+
+ Region spacer = new Region();
+ HBox.setHgrow(spacer, Priority.ALWAYS);
+
+ Button buttonSnapShot = UserInterfaceUtil.getSnapshotButton(scene, "CompileChain");
+
+ HBox hBox = new HBox();
+
+ hBox.getChildren().add(compilationChooser.getCombo());
+ hBox.getChildren().add(spacer);
+ hBox.getChildren().add(buttonSnapShot);
+
+ verticalLayout.getChildren().addAll(hBox, scrollPane);
+
RateLimitedResizeListener resizeListener = new RateLimitedResizeListener(this, 200);
diff --git a/ui/src/main/java/org/adoptopenjdk/jitwatch/ui/main/JITWatchUI.java b/ui/src/main/java/org/adoptopenjdk/jitwatch/ui/main/JITWatchUI.java
index 94c060b6..94bf25c5 100644
--- a/ui/src/main/java/org/adoptopenjdk/jitwatch/ui/main/JITWatchUI.java
+++ b/ui/src/main/java/org/adoptopenjdk/jitwatch/ui/main/JITWatchUI.java
@@ -832,7 +832,9 @@ public void changed(ObservableValue extends CompilationTableRow> arg0, Compila
lblHeap.setStyle(labelStyle);
lblVmVersion.setStyle(labelStyle);
-
+
+ Button buttonSnapShot = UserInterfaceUtil.getSnapshotButton(scene, "JITWatch");
+
hboxBottom.setPadding(new Insets(4));
hboxBottom.setPrefHeight(statusBarHeight);
hboxBottom.setSpacing(4);
@@ -844,6 +846,7 @@ public void changed(ObservableValue extends CompilationTableRow> arg0, Compila
hboxBottom.getChildren().add(lblTweakLog);
hboxBottom.getChildren().add(springRight);
hboxBottom.getChildren().add(lblVmVersion);
+ hboxBottom.getChildren().add(buttonSnapShot);
borderPane.setTop(hboxTop);
borderPane.setCenter(spMain);
diff --git a/ui/src/main/java/org/adoptopenjdk/jitwatch/ui/sandbox/SandboxStage.java b/ui/src/main/java/org/adoptopenjdk/jitwatch/ui/sandbox/SandboxStage.java
index cdee6d45..038f2ade 100644
--- a/ui/src/main/java/org/adoptopenjdk/jitwatch/ui/sandbox/SandboxStage.java
+++ b/ui/src/main/java/org/adoptopenjdk/jitwatch/ui/sandbox/SandboxStage.java
@@ -65,6 +65,8 @@
import javafx.scene.control.TextArea;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
+import javafx.scene.layout.Priority;
+import javafx.scene.layout.Region;
import javafx.scene.layout.VBox;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
@@ -299,7 +301,11 @@ public void handle(ActionEvent e)
showOutput(outputString);
}
});
+
+ BorderPane borderPane = new BorderPane();
+ Scene scene = UserInterfaceUtil.getScene(borderPane, JITWatchUI.WINDOW_WIDTH, JITWatchUI.WINDOW_HEIGHT);
+
HBox hBoxTools = new HBox();
hBoxTools.setSpacing(10);
@@ -312,7 +318,15 @@ public void handle(ActionEvent e)
hBoxTools.getChildren().add(btnResetSandbox);
hBoxTools.getChildren().add(comboBoxVMLanguage);
hBoxTools.getChildren().add(btnRun);
- hBoxTools.getChildren().add(btnOutput);
+ hBoxTools.getChildren().add(btnOutput);
+
+ Region spacer = new Region();
+ HBox.setHgrow(spacer, Priority.ALWAYS);
+
+ Button buttonSnapShot = UserInterfaceUtil.getSnapshotButton(scene, "Sandbox");
+
+ hBoxTools.getChildren().add(spacer);
+ hBoxTools.getChildren().add(buttonSnapShot);
splitVertical.getItems().add(tabPane);
splitVertical.getItems().add(taLog);
@@ -323,14 +337,11 @@ public void handle(ActionEvent e)
vBoxMain.getChildren().add(hBoxTools);
vBoxMain.getChildren().add(splitVertical);
- BorderPane borderPane = new BorderPane();
borderPane.setTop(hBoxTools);
borderPane.setCenter(splitVertical);
initialiseLog();
- Scene scene = UserInterfaceUtil.getScene(borderPane, JITWatchUI.WINDOW_WIDTH, JITWatchUI.WINDOW_HEIGHT);
-
setScene(scene);
setOnCloseRequest(new EventHandler()
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 d301e1c9..17d51f5d 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
@@ -109,7 +109,7 @@ public class TriView extends Stage implements ILineListener, ICompilationChangeL
private CompilationInfo compilationInfo;
- private Label lblMemberInfo;
+ private Label lblStatusBar;
private boolean ignoreComboChanged = false;
@@ -122,7 +122,7 @@ public class TriView extends Stage implements ILineListener, ICompilationChangeL
private TriViewNavigationStack navigationStack;
private IReadOnlyJITDataModel model;
-
+
private boolean selectedProgrammatically = false;
public TriView(final JITWatchUI parent, final JITWatchConfig config)
@@ -252,7 +252,7 @@ public void changed(ObservableValue extends IMetaMember> ov, IMetaMember oldMe
if (!ignoreComboChanged)
{
if (newMember != null)
- {
+ {
if (!selectedProgrammatically)
{
memberSelectionListener.selectMember(newMember, true, true);
@@ -303,12 +303,21 @@ public IMetaMember fromString(String arg0)
splitViewer.prefHeightProperty().bind(vBox.heightProperty());
- lblMemberInfo = new Label();
+ lblStatusBar = new Label();
+
+ Button buttonSnapShot = UserInterfaceUtil.getSnapshotButton(scene, "TriView");
+
+ Region spacerStatus = new Region();
+ HBox.setHgrow(spacerStatus, Priority.ALWAYS);
+
+ HBox hBoxStatusBar = new HBox();
+ hBoxStatusBar.setSpacing(16.0);
+ hBoxStatusBar.getChildren().addAll(lblStatusBar, spacerStatus, buttonSnapShot);
vBox.getChildren().add(hBoxToolBarClass);
vBox.getChildren().add(hBoxToolBarButtons);
vBox.getChildren().add(splitViewer);
- vBox.getChildren().add(lblMemberInfo);
+ vBox.getChildren().add(hBoxStatusBar);
setScene(scene);
@@ -520,7 +529,7 @@ public void setMetaClass(MetaClass metaClass)
if (!members.isEmpty())
{
IMetaMember firstMember = members.get(0);
-
+
if (!selectedProgrammatically)
{
memberSelectionListener.selectMember(firstMember, true, true);
@@ -553,15 +562,15 @@ public void setMember(IMetaMember member, boolean force, int highlightBCI)
}
public void setMember(final IMetaMember member, boolean force, final boolean jumpToSource, final int highlightBCI)
- {
+ {
selectedProgrammatically = true;
if (member == null)
{
clear();
-
+
selectedProgrammatically = false;
-
+
return;
}
@@ -629,10 +638,10 @@ public void setMember(final IMetaMember member, boolean force, final boolean jum
applyActionsIfOffsetMismatchDetected(statusBarBuilder);
- lblMemberInfo.setText(statusBarBuilder.toString());
+ lblStatusBar.setText(statusBarBuilder.toString());
updateBytecodeAndAssembly(jumpToSource, highlightBCI);
-
+
selectedProgrammatically = false;
}
@@ -730,7 +739,7 @@ private void updateBytecodeAndAssembly(boolean focusSource, int highlightBCI)
compilationInfo.setBytecodeSize(Integer.toString(memberBytecode.size()));
}
- lblMemberInfo.setText(S_EMPTY);
+ lblStatusBar.setText(S_EMPTY);
}
}
@@ -796,7 +805,7 @@ public void clear()
classSearch.clear();
- lblMemberInfo.setText(S_EMPTY);
+ lblStatusBar.setText(S_EMPTY);
updateButtons();
}
diff --git a/ui/src/main/java/org/adoptopenjdk/jitwatch/util/UserInterfaceUtil.java b/ui/src/main/java/org/adoptopenjdk/jitwatch/util/UserInterfaceUtil.java
index c3a969c8..214da45d 100644
--- a/ui/src/main/java/org/adoptopenjdk/jitwatch/util/UserInterfaceUtil.java
+++ b/ui/src/main/java/org/adoptopenjdk/jitwatch/util/UserInterfaceUtil.java
@@ -5,22 +5,26 @@
*/
package org.adoptopenjdk.jitwatch.util;
+import java.io.File;
import java.io.InputStream;
import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.text.SimpleDateFormat;
+import java.util.Date;
import java.util.HashMap;
-import java.util.List;
-import org.adoptopenjdk.jitwatch.model.IMetaMember;
-import org.adoptopenjdk.jitwatch.model.IReadOnlyJITDataModel;
import org.adoptopenjdk.jitwatch.model.bytecode.BCAnnotationType;
-import org.adoptopenjdk.jitwatch.model.bytecode.ClassBC;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import javafx.application.Platform;
+import javafx.event.ActionEvent;
+import javafx.event.EventHandler;
import javafx.scene.Parent;
import javafx.scene.Scene;
+import javafx.scene.control.Button;
import javafx.scene.image.Image;
+import javafx.scene.image.ImageView;
+import javafx.scene.image.WritableImage;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
@@ -31,9 +35,12 @@ public final class UserInterfaceUtil
// https://www.iconfinder.com/icons/173960/tick_icon#size=16
public static final Image IMAGE_TICK;
+ public static final Image IMAGE_CAMERA;
+
public static final String FONT_MONOSPACE_FAMILY;
public static final String FONT_MONOSPACE_SIZE;
- public static final boolean ADD_CLOSE_DECORATION; // for fullscreen JavaFX systems
+ public static final boolean ADD_CLOSE_DECORATION; // for fullscreen JavaFX
+ // systems
private UserInterfaceUtil()
{
@@ -42,6 +49,7 @@ private UserInterfaceUtil()
static
{
IMAGE_TICK = loadResource("/images/tick.png");
+ IMAGE_CAMERA = loadResource("/images/camera.png");
FONT_MONOSPACE_FAMILY = System.getProperty("monospaceFontFamily", Font.font(java.awt.Font.MONOSPACED, 12).getName());
FONT_MONOSPACE_SIZE = System.getProperty("monospaceFontSize", "12");
@@ -68,6 +76,60 @@ private static Image loadResource(String path)
return result;
}
+ public static Button getSnapshotButton(final Scene scene, final String filenamePrefix)
+ {
+ Button buttonSnapShot = new Button();
+
+ Image image = UserInterfaceUtil.IMAGE_CAMERA;
+
+ buttonSnapShot.setGraphic(new ImageView(image));
+
+ buttonSnapShot.setOnAction(new EventHandler()
+ {
+ @Override
+ public void handle(ActionEvent e)
+ {
+ takeSnapShot(scene, filenamePrefix);
+ }
+ });
+
+ return buttonSnapShot;
+ }
+
+ private static void takeSnapShot(Scene scene, String filenamePrefix)
+ {
+ WritableImage imageSnap = new WritableImage((int) scene.getWidth(), (int) scene.getHeight());
+
+ scene.snapshot(imageSnap);
+
+ SimpleDateFormat sfd = new SimpleDateFormat("yyyy.MM.dd.HH.mm.ss");
+
+ try
+ {
+ String snapshotFilename = filenamePrefix + "-snapshot-" + sfd.format(new Date()) + ".png";
+
+ Class> classImageIO = Class.forName("javax.imageio.ImageIO");
+
+ Class> classSwingFXUtils = Class.forName("javafx.embed.swing.SwingFXUtils");
+
+ Method methodWrite = classImageIO.getMethod("write",
+ new Class[] { java.awt.image.RenderedImage.class, String.class, File.class });
+
+ Method methodFromFXImage = classSwingFXUtils.getMethod("fromFXImage",
+ new Class[] { javafx.scene.image.Image.class, java.awt.image.BufferedImage.class });
+
+ methodWrite.invoke(null,
+ new Object[] {
+ methodFromFXImage.invoke(null, new Object[] { imageSnap, null }),
+ "png",
+ new File(snapshotFilename) });
+ }
+ catch (Throwable t)
+ {
+ logger.error("Could not create snapshot", t);
+ }
+ }
+
public static Scene getScene(Parent rootNode, double width, double height)
{
Scene scene = new Scene(rootNode, width, height);
diff --git a/ui/src/main/resources/images/camera.png b/ui/src/main/resources/images/camera.png
new file mode 100755
index 00000000..5f818d25
Binary files /dev/null and b/ui/src/main/resources/images/camera.png differ