All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.adoptopenjdk.jitwatch.ui.main.ClassMemberList Maven / Gradle / Ivy

/*
 * Copyright (c) 2013-2017 Chris Newland.
 * Licensed under https://github.com/AdoptOpenJDK/jitwatch/blob/master/LICENSE-BSD
 * Instructions: https://github.com/AdoptOpenJDK/jitwatch/wiki
 */
package org.adoptopenjdk.jitwatch.ui.main;

import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.C_NEWLINE;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_EMPTY;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.control.MenuItem;
import javafx.scene.control.Tooltip;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.VBox;
import javafx.util.Callback;

import org.adoptopenjdk.jitwatch.core.JITWatchConfig;
import org.adoptopenjdk.jitwatch.intrinsic.IntrinsicFinder;
import org.adoptopenjdk.jitwatch.model.IMetaMember;
import org.adoptopenjdk.jitwatch.model.MetaClass;
import org.adoptopenjdk.jitwatch.util.UserInterfaceUtil;

public class ClassMemberList extends VBox
{
	private CheckBox cbOnlyCompiled;
	private ListView memberList;
	private MetaClass metaClass = null;
	private JITWatchConfig config;

	private boolean selectedProgrammatically = false;

	private List listeners = new ArrayList<>();

	public void registerListener(IMemberSelectedListener listener)
	{
		listeners.add(listener);
	}

	public void clear()
	{
		if (memberList != null)
		{
			memberList.getItems().clear();
		}

		metaClass = null;
	}

	private void notifyListeners(IMetaMember member, boolean openTriView)
	{
		for (IMemberSelectedListener listener : listeners)
		{
			listener.setSelectedMetaMember(member, openTriView);
		}
	}

	public ClassMemberList(final IStageAccessProxy parent, final JITWatchConfig config)
	{
		this.config = config;

		cbOnlyCompiled = new CheckBox("Hide non JIT-compiled class members");
		cbOnlyCompiled.setTooltip(new Tooltip("Hide class members (methods and constructors) that were not JIT-compiled."));

		cbOnlyCompiled.setSelected(config.isShowOnlyCompiledMembers());

		cbOnlyCompiled.selectedProperty().addListener(new ChangeListener()
		{
			@Override
			public void changed(ObservableValue ov, Boolean oldVal, Boolean newVal)
			{
				config.setShowOnlyCompiledMembers(newVal);
				config.saveConfig();
				refresh();
			}
		});

		cbOnlyCompiled.setStyle("-fx-background-color:#dddddd; -fx-padding:4px");
		cbOnlyCompiled.prefWidthProperty().bind(widthProperty());

		memberList = new ListView();
		memberList.getSelectionModel().selectedItemProperty().addListener(new ChangeListener()
		{
			@Override
			public void changed(ObservableValue arg0, IMetaMember oldVal, IMetaMember newVal)
			{
				if (!selectedProgrammatically)
				{
					notifyListeners(newVal, true);
				}
			}
		});

		memberList.setCellFactory(new Callback, ListCell>()
		{
			@Override
			public ListCell call(ListView arg0)
			{
				return new MetaMethodCell();
			}
		});

		final ContextMenu menuCompiled = buildContextMenuCompiledMember(parent);
		final ContextMenu menuUncompiled = buildContextMenuUncompiledMember(parent);

		memberList.addEventHandler(MouseEvent.MOUSE_CLICKED, getEventHandlerContextMenu(menuCompiled, menuUncompiled));

		memberList.addEventHandler(MouseEvent.MOUSE_ENTERED, new EventHandler()
		{
			@Override
			public void handle(MouseEvent e)
			{
				menuCompiled.hide();
				menuUncompiled.hide();
			}
		});

		getChildren().add(cbOnlyCompiled);
		getChildren().add(memberList);

		memberList.prefHeightProperty().bind(heightProperty());
	}

	private EventHandler getEventHandlerContextMenu(final ContextMenu contextMenuCompiled,
			final ContextMenu contextMenuNotCompiled)
	{
		return new EventHandler()
		{
			@Override
			public void handle(MouseEvent e)
			{
				if (e.getButton() == MouseButton.SECONDARY)
				{
					IMetaMember selectedMember = memberList.getSelectionModel().getSelectedItem();

					if (selectedMember.isCompiled())
					{
						contextMenuCompiled.show(memberList, e.getScreenX(), e.getScreenY());
					}
					else
					{
						contextMenuNotCompiled.show(memberList, e.getScreenX(), e.getScreenY());
					}
				}
			}
		};
	}

	private ContextMenu buildContextMenuCompiledMember(IStageAccessProxy parent)
	{
		final ContextMenu menu = new ContextMenu();

		MenuItem menuItemTriView = new MenuItem("Show TriView");
		MenuItem menuItemInlinedInto = new MenuItem("Show inlined into");

		MenuItem menuItemIntrinsics = new MenuItem("Show intrinsics used");
		MenuItem menuItemCallChain = new MenuItem("Show compile chain");
		MenuItem menuItemOptimizedVCalls = new MenuItem("Show optimized virtual calls");

		menu.getItems().add(menuItemTriView);
		menu.getItems().add(menuItemInlinedInto);
		menu.getItems().add(menuItemIntrinsics);
		menu.getItems().add(menuItemCallChain);
		menu.getItems().add(menuItemOptimizedVCalls);

		menuItemTriView.setOnAction(getEventHandlerMenuItemTriView(parent));

		menuItemInlinedInto.setOnAction(getEventHandlerMenuItemInlinedInto(parent));

		menuItemIntrinsics.setOnAction(getEventHandlerMenuItemIntrinsics(parent));

		menuItemCallChain.setOnAction(getEventHandlerMenuItemCallChain(parent));

		menuItemOptimizedVCalls.setOnAction(getEventHandlerMenuItemOptimizedVCall(parent));

		return menu;
	}

	private ContextMenu buildContextMenuUncompiledMember(IStageAccessProxy parent)
	{
		ContextMenu menu = new ContextMenu();

		MenuItem menuItemTriView = new MenuItem("Show TriView");
		MenuItem menuItemInlinedInto = new MenuItem("Show inlined into");

		menu.getItems().add(menuItemTriView);
		menu.getItems().add(menuItemInlinedInto);

		menuItemTriView.setOnAction(getEventHandlerMenuItemTriView(parent));
		menuItemInlinedInto.setOnAction(getEventHandlerMenuItemInlinedInto(parent));

		return menu;
	}

	private EventHandler getEventHandlerMenuItemTriView(final IStageAccessProxy parent)
	{
		return new EventHandler()
		{
			@Override
			public void handle(ActionEvent e)
			{
				parent.openTriView(memberList.getSelectionModel().getSelectedItem(), false);
			}
		};
	}

	private EventHandler getEventHandlerMenuItemInlinedInto(final IStageAccessProxy parent)
	{
		return new EventHandler()
		{
			@Override
			public void handle(ActionEvent e)
			{
				parent.openInlinedIntoReport(memberList.getSelectionModel().getSelectedItem());
			}
		};
	}

	private EventHandler getEventHandlerMenuItemIntrinsics(final IStageAccessProxy parent)
	{
		return new EventHandler()
		{
			@Override
			public void handle(ActionEvent e)
			{
				IMetaMember member = memberList.getSelectionModel().getSelectedItem();

				String intrinsicsUsed = findIntrinsicsUsedByMember(member);

				parent.openTextViewer("Intrinsics used by " + member.toString(), intrinsicsUsed, false, false);
			}
		};
	}

	private EventHandler getEventHandlerMenuItemCallChain(final IStageAccessProxy parent)
	{
		return new EventHandler()
		{
			@Override
			public void handle(ActionEvent e)
			{
				parent.openCompileChain(memberList.getSelectionModel().getSelectedItem());
			}
		};
	}

	private EventHandler getEventHandlerMenuItemOptimizedVCall(final IStageAccessProxy parent)
	{
		return new EventHandler()
		{
			@Override
			public void handle(ActionEvent e)
			{
				parent.openOptmizedVCallReport(memberList.getSelectionModel().getSelectedItem());
			}
		};
	}

	private String findIntrinsicsUsedByMember(IMetaMember member)
	{
		StringBuilder builder = new StringBuilder();

		IntrinsicFinder finder = new IntrinsicFinder();

		Map intrinsics = finder.findIntrinsics(member);

		if (intrinsics.size() > 0)
		{
			addArrowWithNewLineToEachIntrinsicEntry(builder, intrinsics);
		}
		else
		{
			builder.append("No intrinsics used in this method");
		}

		return builder.toString();
	}

	private void addArrowWithNewLineToEachIntrinsicEntry(StringBuilder builder, Map intrinsics)
	{
		for (Map.Entry entry : intrinsics.entrySet())
		{
			builder.append(entry.getKey()).append(" -> ").append(entry.getValue()).append(C_NEWLINE);
		}
	}

	public void setMetaClass(MetaClass metaClass)
	{
		this.metaClass = metaClass;

		List members = metaClass.getMetaMembers();

		if (members.size() > 0)
		{
			selectMember(members.get(0));
		}

		refresh();
	}

	private void refresh()
	{
		clearClassMembers();

		if (metaClass != null)
		{
			List metaMembers = metaClass.getMetaMembers();

			for (IMetaMember member : metaMembers)
			{
				if (member.isCompiled() || !config.isShowOnlyCompiledMembers())
				{
					addMember(member);
				}
			}
		}
	}

	private void addMember(IMetaMember member)
	{
		memberList.getItems().add(member);
	}

	public void clearClassMembers()
	{
		memberList.getItems().clear();
	}

	public void selectMember(IMetaMember selected)
	{
		selectedProgrammatically = true;

		memberList.getSelectionModel().clearSelection();

		for (int i = 0; i < memberList.getItems().size(); i++)
		{
			IMetaMember member = memberList.getItems().get(i);

			if (member.toString().equals(selected.toString()))
			{
				memberList.getSelectionModel().select(i);

				memberList.getFocusModel().focus(i);

				memberList.scrollTo(i);
			}
		}

		selectedProgrammatically = false;
	}

	static class MetaMethodCell extends ListCell
	{
		@Override
		public void updateItem(IMetaMember item, boolean empty)
		{
			super.updateItem(item, empty);

			if (item == null)
			{
				setText(S_EMPTY);
				setGraphic(null);
			}
			else
			{
				setText(item.toStringUnqualifiedMethodName(false, false));

				if (UserInterfaceUtil.IMAGE_TICK != null && item.isCompiled())
				{
					setGraphic(new ImageView(UserInterfaceUtil.IMAGE_TICK));
				}
				else
				{
					setGraphic(null);
				}
			}
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy