Loading src/main/java/jetklee/CompleteMemoryRetriever.java 0 → 100644 +116 −0 Original line number Diff line number Diff line package jetklee; import java.util.ArrayList; import java.util.HashMap; /** * Retrieves the complete memory of a node (decompress memory). */ public class CompleteMemoryRetriever { public static NodeMemory.Memory getCompleteMemory(Node node) { HashMap<Integer, NodeMemory.ObjectState> complete_memory = new HashMap<>(); ArrayList<Node> nodes = new ArrayList<>(); nodes.add(node); while (node.getParent() != null) { node = node.getParent(); nodes.add(node); } // The nodes are in order from leaf to root, traverse them in reverse order (from root to leaf) for (int i = nodes.size() - 1; i >= 0; i--) { NodeMemory.Memory node_memory = nodes.get(i).getMemory().getMemory(); // Add newly added objects for (NodeMemory.ObjectState addition : node_memory.additions()) { complete_memory.put(addition.objID(), addition); } // Apply changes to changed objects for (NodeMemory.ObjectState change : node_memory.changes()) { NodeMemory.ObjectState oldObjectState = complete_memory.get(change.objID()); complete_memory.put(change.objID(), mergeObjectState(oldObjectState, change)); } // Remove deleted objects for (NodeMemory.Deletion deletion : node_memory.deletions()) { complete_memory.remove(deletion.objID()); } } // Save the complete memory in additions return new NodeMemory.Memory(new ArrayList<>(complete_memory.values()), new ArrayList<>(), new ArrayList<>()); } private static NodeMemory.ObjectState mergeObjectState(NodeMemory.ObjectState a, NodeMemory.ObjectState b) { NodeMemory.Plane mergedSegmentPlane = mergePlane(a.segmentPlane(), b.segmentPlane()); NodeMemory.Plane mergedOffsetPlane = mergePlane(a.offsetPlane(), b.offsetPlane()); return new NodeMemory.ObjectState( a.objID(), a.type(), a.segment(), a.name(), a.size(), a.isLocal(), a.isGlobal(), a.isFixed(), a.isUserSpec(), a.isLazy(), a.symAddress(), a.copyOnWriteOwner(), a.readOnly(), a.allocSite(), mergedSegmentPlane, mergedOffsetPlane); } private static NodeMemory.Plane mergePlane(NodeMemory.Plane a, NodeMemory.Plane b) { if (a == null && b == null) { return null; } if (a == null) { return b; } if (b == null) { return a; } return new NodeMemory.Plane( a.type(), a.memoryObjectID(), a.rootObject(), a.sizeBound(), a.initialized(), a.symbolic(), a.initialValue(), mergeDiff(a.concreteStore(), b.concreteStore()), mergeDiff(a.concreteMask(), b.concreteMask()), mergeDiff(a.knownSymbolics(), b.knownSymbolics()), mergeUpdates(a.updates(), b.updates())); } private static NodeMemory.Updates mergeUpdates(NodeMemory.Updates a, NodeMemory.Updates b) { NodeMemory.Updates mergedUpdates = new NodeMemory.Updates(); if (a != null) { mergedUpdates.putAll(a); } if (b != null) { mergedUpdates.putAll(b); } return mergedUpdates; } public static NodeMemory.Diff mergeDiff(NodeMemory.Diff a, NodeMemory.Diff b) { NodeMemory.ByteMap mergedByteMap = new NodeMemory.ByteMap(); // Copy all entries from 'a' into 'mergedByteMap' a.additions().forEach((key, indices) -> { mergedByteMap.put(key, new ArrayList<>(indices)); }); // Delete all entries from 'b's deletions b.deletions().forEach((key, indices) -> { mergedByteMap.get(key).removeAll(indices); }); // Remove all empty entries from 'mergedByteMap' mergedByteMap.entrySet().removeIf(entry -> entry.getValue().isEmpty()); // Iterate over each addition in 'b' and merge it into 'mergedByteMap' b.additions().forEach((key, indices) -> { // If the key exists in 'mergedByteMap', merge the indices by adding all elements of 'indices' to 'mergedByteMap' mergedByteMap.merge(key, indices, (v1, v2) -> { v1.addAll(v2); return v1; }); }); return new NodeMemory.Diff( mergedByteMap, // The complete state does not contain deletions new NodeMemory.ByteMap()); } } src/main/java/jetklee/MemoryViewer.java +125 −354 File changed.Preview size limit exceeded, changes collapsed. Show changes src/main/java/jetklee/ObjectInfoViewer.java 0 → 100644 +130 −0 Original line number Diff line number Diff line package jetklee; import javax.swing.*; import java.awt.*; import java.util.ArrayList; public class ObjectInfoViewer { private final SourceViewerLL sourceLL; private final JPanel objectInfoPanel; public ObjectInfoViewer(SourceViewerLL sourceLL, JPanel objectInfoPanel) { this.sourceLL = sourceLL; this.objectInfoPanel = objectInfoPanel; } public void displayObjectInfo(JList<String> objectsList, NodeMemory.Memory memory, ArrayList<NodeMemory.ObjectState> objects) { objectInfoPanel.removeAll(); if (objectsList.getSelectedIndex() < 0) { objectInfoPanel.revalidate(); objectInfoPanel.repaint(); return; } int selected = Integer.parseInt(objectsList.getSelectedValue().split(" ")[0]); boolean isDeletion = memory.deletions().stream() .anyMatch(deletion -> deletion.objID() == selected); if (isDeletion) { return; } NodeMemory.ObjectState currentObjectState = objects.stream() .filter(obj -> obj.objID() == selected) .findFirst() .orElse(null); if (currentObjectState == null) { return; } StringBuilder htmlContent = new StringBuilder("<html><body style='font-family:Arial;padding:10px;'>"); // Row 1: ID (Key and Value are bold) htmlContent.append("<b style='color:blue;'>objId: </b>").append(currentObjectState.objID()).append("<br>"); // Row 2: Segment, Name, Size, Copy-On-Write Owner, Symbolic Address appendKeyValueInlineNonBold(htmlContent, "segment", currentObjectState.segment()); appendKeyValueInlineNonBold(htmlContent, "name", currentObjectState.name()); appendKeyValueInlineNonBold(htmlContent, "size", currentObjectState.size()); appendKeyValueInlineNonBold(htmlContent, "copyOnWriteOwner", currentObjectState.copyOnWriteOwner()); appendKeyValueInlineNonBold(htmlContent, "symbolicAddress", currentObjectState.symAddress()); htmlContent.append("<br>"); // Row 3: Local, Global, Fixed, User Spec, Lazy, Read-Only appendKeyValueInlineNonBold(htmlContent, "local", currentObjectState.isLocal()); appendKeyValueInlineNonBold(htmlContent, "global", currentObjectState.isGlobal()); appendKeyValueInlineNonBold(htmlContent, "fixed", currentObjectState.isFixed()); appendKeyValueInlineNonBold(htmlContent, "userSpec", currentObjectState.isUserSpec()); appendKeyValueInlineNonBold(htmlContent, "lazy", currentObjectState.isLazy()); appendKeyValueInlineNonBold(htmlContent, "readOnly", currentObjectState.readOnly()); htmlContent.append("<br>"); htmlContent.append("<br>"); if (currentObjectState.allocSite() != null) { htmlContent.append("<b style='color:blue;'>allocSite:</b><br>"); NodeMemory.AllocSite allocSite = currentObjectState.allocSite(); String name = allocSite.name(); String row = ""; if (name != null && !name.isEmpty()) { row = String.valueOf(sourceLL.findDefinitionLine(name)); } htmlContent.append(formatAllocSiteAsList(allocSite, row)); } htmlContent.append("<br>"); if (currentObjectState.offsetPlane() != null) { htmlContent.append("<b style='color:blue;'>offsetPlane</b>"); htmlContent.append("<br>"); appendPlaneDetailsHTML(htmlContent, currentObjectState.offsetPlane()); } htmlContent.append("<br>"); htmlContent.append("<br>"); // Segment Plane if (currentObjectState.segmentPlane() != null) { htmlContent.append("<b style='color:blue;'>segmentPlane</b>"); htmlContent.append("<br>"); appendPlaneDetailsHTML(htmlContent, currentObjectState.segmentPlane()); } htmlContent.append("</body></html>"); JEditorPane editorPane = new JEditorPane(); editorPane.setContentType("text/html"); editorPane.setText(htmlContent.toString()); editorPane.setEditable(false); JScrollPane scrollPane = new JScrollPane(editorPane); scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); objectInfoPanel.add(scrollPane, BorderLayout.CENTER); objectInfoPanel.revalidate(); objectInfoPanel.repaint(); } private String formatAllocSiteAsList(NodeMemory.AllocSite allocSite, String row) { return " - <span style='color:blue;'>scope:</span> " + allocSite.scope() + "<br>" + " - <span style='color:blue;'>name:</span> " + allocSite.name() + "<br>" + " - <span style='color:blue;'>row:</span> " + row + "<br>" + " - <span style='color:blue;'>code:</span> " + allocSite.code() + "<br>"; } private void appendKeyValueInlineNonBold(StringBuilder html, String key, Object value) { html.append("<span style='color:blue;'>").append(key).append(":</span> <span style='color:black;'>").append(value).append("</span> "); } private void appendPlaneDetailsHTML(StringBuilder html, NodeMemory.Plane plane) { appendKeyValueInlineNonBold(html, "rootObject", plane.rootObject()); appendKeyValueInlineNonBold(html, "initialValue", plane.initialValue()); appendKeyValueInlineNonBold(html, "sizeBound", plane.sizeBound()); appendKeyValueInlineNonBold(html, "initialized", plane.initialized()); appendKeyValueInlineNonBold(html, "symbolic", plane.symbolic()); } } src/main/java/jetklee/ObjectStateDocListener.java 0 → 100644 +69 −0 Original line number Diff line number Diff line package jetklee; import javax.swing.*; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import static jetklee.Styles.BACKGROUND_COLOR; import static jetklee.Styles.DELETIONS_COLOR; /** * A custom DocumentListener that filters a list based on user input in a JTextField. */ public class ObjectStateDocListener implements DocumentListener { private JTextField entryField; private JList<String> objectsList; private DefaultListModel<String> originalModel; public ObjectStateDocListener(JTextField entryField, JList<String> objectsList) { this.entryField = entryField; this.objectsList = objectsList; this.originalModel = (DefaultListModel<String>) objectsList.getModel(); } @Override public void insertUpdate(DocumentEvent e) { filterList(); } @Override public void removeUpdate(DocumentEvent e) { filterList(); } @Override public void changedUpdate(DocumentEvent e) { filterList(); } /** * Filters the list based on the text entered in the JTextField. */ private void filterList() { String input = entryField.getText().toLowerCase(); if (input.isEmpty()) { objectsList.setModel(originalModel); objectsList.clearSelection(); entryField.setBackground(BACKGROUND_COLOR); return; } // Find matching object names DefaultListModel<String> filteredModel = new DefaultListModel<>(); for (int i = 0; i < originalModel.getSize(); i++) { String item = originalModel.getElementAt(i).toLowerCase(); if (item.contains(input)) { filteredModel.addElement(originalModel.getElementAt(i)); } } objectsList.setModel(filteredModel); if (filteredModel.isEmpty()) { entryField.setBackground(DELETIONS_COLOR); } else { entryField.setBackground(BACKGROUND_COLOR); } } } src/main/java/jetklee/ProgressExplorer.java +1 −1 Original line number Diff line number Diff line Loading @@ -273,7 +273,7 @@ public class ProgressExplorer implements ListSelectionListener, MouseWheelListen private void displayNodePane(Node node) { contextViewer.displayContext(node.getInfo()); constraintsViewer.displayConstraints(node.getInfo().getConstraints()); memoryViewer.displayMemory(node, sourceLL); memoryViewer.setupAndDisplayMemory(node, sourceLL); nodeTabbedPane.setVisible(true); splitPane.setDividerLocation(0.5); Loading Loading
src/main/java/jetklee/CompleteMemoryRetriever.java 0 → 100644 +116 −0 Original line number Diff line number Diff line package jetklee; import java.util.ArrayList; import java.util.HashMap; /** * Retrieves the complete memory of a node (decompress memory). */ public class CompleteMemoryRetriever { public static NodeMemory.Memory getCompleteMemory(Node node) { HashMap<Integer, NodeMemory.ObjectState> complete_memory = new HashMap<>(); ArrayList<Node> nodes = new ArrayList<>(); nodes.add(node); while (node.getParent() != null) { node = node.getParent(); nodes.add(node); } // The nodes are in order from leaf to root, traverse them in reverse order (from root to leaf) for (int i = nodes.size() - 1; i >= 0; i--) { NodeMemory.Memory node_memory = nodes.get(i).getMemory().getMemory(); // Add newly added objects for (NodeMemory.ObjectState addition : node_memory.additions()) { complete_memory.put(addition.objID(), addition); } // Apply changes to changed objects for (NodeMemory.ObjectState change : node_memory.changes()) { NodeMemory.ObjectState oldObjectState = complete_memory.get(change.objID()); complete_memory.put(change.objID(), mergeObjectState(oldObjectState, change)); } // Remove deleted objects for (NodeMemory.Deletion deletion : node_memory.deletions()) { complete_memory.remove(deletion.objID()); } } // Save the complete memory in additions return new NodeMemory.Memory(new ArrayList<>(complete_memory.values()), new ArrayList<>(), new ArrayList<>()); } private static NodeMemory.ObjectState mergeObjectState(NodeMemory.ObjectState a, NodeMemory.ObjectState b) { NodeMemory.Plane mergedSegmentPlane = mergePlane(a.segmentPlane(), b.segmentPlane()); NodeMemory.Plane mergedOffsetPlane = mergePlane(a.offsetPlane(), b.offsetPlane()); return new NodeMemory.ObjectState( a.objID(), a.type(), a.segment(), a.name(), a.size(), a.isLocal(), a.isGlobal(), a.isFixed(), a.isUserSpec(), a.isLazy(), a.symAddress(), a.copyOnWriteOwner(), a.readOnly(), a.allocSite(), mergedSegmentPlane, mergedOffsetPlane); } private static NodeMemory.Plane mergePlane(NodeMemory.Plane a, NodeMemory.Plane b) { if (a == null && b == null) { return null; } if (a == null) { return b; } if (b == null) { return a; } return new NodeMemory.Plane( a.type(), a.memoryObjectID(), a.rootObject(), a.sizeBound(), a.initialized(), a.symbolic(), a.initialValue(), mergeDiff(a.concreteStore(), b.concreteStore()), mergeDiff(a.concreteMask(), b.concreteMask()), mergeDiff(a.knownSymbolics(), b.knownSymbolics()), mergeUpdates(a.updates(), b.updates())); } private static NodeMemory.Updates mergeUpdates(NodeMemory.Updates a, NodeMemory.Updates b) { NodeMemory.Updates mergedUpdates = new NodeMemory.Updates(); if (a != null) { mergedUpdates.putAll(a); } if (b != null) { mergedUpdates.putAll(b); } return mergedUpdates; } public static NodeMemory.Diff mergeDiff(NodeMemory.Diff a, NodeMemory.Diff b) { NodeMemory.ByteMap mergedByteMap = new NodeMemory.ByteMap(); // Copy all entries from 'a' into 'mergedByteMap' a.additions().forEach((key, indices) -> { mergedByteMap.put(key, new ArrayList<>(indices)); }); // Delete all entries from 'b's deletions b.deletions().forEach((key, indices) -> { mergedByteMap.get(key).removeAll(indices); }); // Remove all empty entries from 'mergedByteMap' mergedByteMap.entrySet().removeIf(entry -> entry.getValue().isEmpty()); // Iterate over each addition in 'b' and merge it into 'mergedByteMap' b.additions().forEach((key, indices) -> { // If the key exists in 'mergedByteMap', merge the indices by adding all elements of 'indices' to 'mergedByteMap' mergedByteMap.merge(key, indices, (v1, v2) -> { v1.addAll(v2); return v1; }); }); return new NodeMemory.Diff( mergedByteMap, // The complete state does not contain deletions new NodeMemory.ByteMap()); } }
src/main/java/jetklee/MemoryViewer.java +125 −354 File changed.Preview size limit exceeded, changes collapsed. Show changes
src/main/java/jetklee/ObjectInfoViewer.java 0 → 100644 +130 −0 Original line number Diff line number Diff line package jetklee; import javax.swing.*; import java.awt.*; import java.util.ArrayList; public class ObjectInfoViewer { private final SourceViewerLL sourceLL; private final JPanel objectInfoPanel; public ObjectInfoViewer(SourceViewerLL sourceLL, JPanel objectInfoPanel) { this.sourceLL = sourceLL; this.objectInfoPanel = objectInfoPanel; } public void displayObjectInfo(JList<String> objectsList, NodeMemory.Memory memory, ArrayList<NodeMemory.ObjectState> objects) { objectInfoPanel.removeAll(); if (objectsList.getSelectedIndex() < 0) { objectInfoPanel.revalidate(); objectInfoPanel.repaint(); return; } int selected = Integer.parseInt(objectsList.getSelectedValue().split(" ")[0]); boolean isDeletion = memory.deletions().stream() .anyMatch(deletion -> deletion.objID() == selected); if (isDeletion) { return; } NodeMemory.ObjectState currentObjectState = objects.stream() .filter(obj -> obj.objID() == selected) .findFirst() .orElse(null); if (currentObjectState == null) { return; } StringBuilder htmlContent = new StringBuilder("<html><body style='font-family:Arial;padding:10px;'>"); // Row 1: ID (Key and Value are bold) htmlContent.append("<b style='color:blue;'>objId: </b>").append(currentObjectState.objID()).append("<br>"); // Row 2: Segment, Name, Size, Copy-On-Write Owner, Symbolic Address appendKeyValueInlineNonBold(htmlContent, "segment", currentObjectState.segment()); appendKeyValueInlineNonBold(htmlContent, "name", currentObjectState.name()); appendKeyValueInlineNonBold(htmlContent, "size", currentObjectState.size()); appendKeyValueInlineNonBold(htmlContent, "copyOnWriteOwner", currentObjectState.copyOnWriteOwner()); appendKeyValueInlineNonBold(htmlContent, "symbolicAddress", currentObjectState.symAddress()); htmlContent.append("<br>"); // Row 3: Local, Global, Fixed, User Spec, Lazy, Read-Only appendKeyValueInlineNonBold(htmlContent, "local", currentObjectState.isLocal()); appendKeyValueInlineNonBold(htmlContent, "global", currentObjectState.isGlobal()); appendKeyValueInlineNonBold(htmlContent, "fixed", currentObjectState.isFixed()); appendKeyValueInlineNonBold(htmlContent, "userSpec", currentObjectState.isUserSpec()); appendKeyValueInlineNonBold(htmlContent, "lazy", currentObjectState.isLazy()); appendKeyValueInlineNonBold(htmlContent, "readOnly", currentObjectState.readOnly()); htmlContent.append("<br>"); htmlContent.append("<br>"); if (currentObjectState.allocSite() != null) { htmlContent.append("<b style='color:blue;'>allocSite:</b><br>"); NodeMemory.AllocSite allocSite = currentObjectState.allocSite(); String name = allocSite.name(); String row = ""; if (name != null && !name.isEmpty()) { row = String.valueOf(sourceLL.findDefinitionLine(name)); } htmlContent.append(formatAllocSiteAsList(allocSite, row)); } htmlContent.append("<br>"); if (currentObjectState.offsetPlane() != null) { htmlContent.append("<b style='color:blue;'>offsetPlane</b>"); htmlContent.append("<br>"); appendPlaneDetailsHTML(htmlContent, currentObjectState.offsetPlane()); } htmlContent.append("<br>"); htmlContent.append("<br>"); // Segment Plane if (currentObjectState.segmentPlane() != null) { htmlContent.append("<b style='color:blue;'>segmentPlane</b>"); htmlContent.append("<br>"); appendPlaneDetailsHTML(htmlContent, currentObjectState.segmentPlane()); } htmlContent.append("</body></html>"); JEditorPane editorPane = new JEditorPane(); editorPane.setContentType("text/html"); editorPane.setText(htmlContent.toString()); editorPane.setEditable(false); JScrollPane scrollPane = new JScrollPane(editorPane); scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); objectInfoPanel.add(scrollPane, BorderLayout.CENTER); objectInfoPanel.revalidate(); objectInfoPanel.repaint(); } private String formatAllocSiteAsList(NodeMemory.AllocSite allocSite, String row) { return " - <span style='color:blue;'>scope:</span> " + allocSite.scope() + "<br>" + " - <span style='color:blue;'>name:</span> " + allocSite.name() + "<br>" + " - <span style='color:blue;'>row:</span> " + row + "<br>" + " - <span style='color:blue;'>code:</span> " + allocSite.code() + "<br>"; } private void appendKeyValueInlineNonBold(StringBuilder html, String key, Object value) { html.append("<span style='color:blue;'>").append(key).append(":</span> <span style='color:black;'>").append(value).append("</span> "); } private void appendPlaneDetailsHTML(StringBuilder html, NodeMemory.Plane plane) { appendKeyValueInlineNonBold(html, "rootObject", plane.rootObject()); appendKeyValueInlineNonBold(html, "initialValue", plane.initialValue()); appendKeyValueInlineNonBold(html, "sizeBound", plane.sizeBound()); appendKeyValueInlineNonBold(html, "initialized", plane.initialized()); appendKeyValueInlineNonBold(html, "symbolic", plane.symbolic()); } }
src/main/java/jetklee/ObjectStateDocListener.java 0 → 100644 +69 −0 Original line number Diff line number Diff line package jetklee; import javax.swing.*; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import static jetklee.Styles.BACKGROUND_COLOR; import static jetklee.Styles.DELETIONS_COLOR; /** * A custom DocumentListener that filters a list based on user input in a JTextField. */ public class ObjectStateDocListener implements DocumentListener { private JTextField entryField; private JList<String> objectsList; private DefaultListModel<String> originalModel; public ObjectStateDocListener(JTextField entryField, JList<String> objectsList) { this.entryField = entryField; this.objectsList = objectsList; this.originalModel = (DefaultListModel<String>) objectsList.getModel(); } @Override public void insertUpdate(DocumentEvent e) { filterList(); } @Override public void removeUpdate(DocumentEvent e) { filterList(); } @Override public void changedUpdate(DocumentEvent e) { filterList(); } /** * Filters the list based on the text entered in the JTextField. */ private void filterList() { String input = entryField.getText().toLowerCase(); if (input.isEmpty()) { objectsList.setModel(originalModel); objectsList.clearSelection(); entryField.setBackground(BACKGROUND_COLOR); return; } // Find matching object names DefaultListModel<String> filteredModel = new DefaultListModel<>(); for (int i = 0; i < originalModel.getSize(); i++) { String item = originalModel.getElementAt(i).toLowerCase(); if (item.contains(input)) { filteredModel.addElement(originalModel.getElementAt(i)); } } objectsList.setModel(filteredModel); if (filteredModel.isEmpty()) { entryField.setBackground(DELETIONS_COLOR); } else { entryField.setBackground(BACKGROUND_COLOR); } } }
src/main/java/jetklee/ProgressExplorer.java +1 −1 Original line number Diff line number Diff line Loading @@ -273,7 +273,7 @@ public class ProgressExplorer implements ListSelectionListener, MouseWheelListen private void displayNodePane(Node node) { contextViewer.displayContext(node.getInfo()); constraintsViewer.displayConstraints(node.getInfo().getConstraints()); memoryViewer.displayMemory(node, sourceLL); memoryViewer.setupAndDisplayMemory(node, sourceLL); nodeTabbedPane.setVisible(true); splitPane.setDividerLocation(0.5); Loading