Commit b1a9dce5 authored by EmaJasekova's avatar EmaJasekova
Browse files

Refactor MemoryViewer [in progress]

parent 91faf151
Loading
Loading
Loading
Loading
+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());
    }
}
+125 −354

File changed.

Preview size limit exceeded, changes collapsed.

+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 "&nbsp;&nbsp;- <span style='color:blue;'>scope:</span> " + allocSite.scope() + "<br>"
                + "&nbsp;&nbsp;- <span style='color:blue;'>name:</span> " + allocSite.name() + "<br>"
                + "&nbsp;&nbsp;- <span style='color:blue;'>row:</span> " + row + "<br>"
                + "&nbsp;&nbsp;- <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>&nbsp;&nbsp;&nbsp;");
    }

    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());
    }
}
+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);
        }
    }
}
+1 −1
Original line number Diff line number Diff line
@@ -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