Mega Code Archive

 
Categories / Java / Development Class
 

Stack memory view

/********************************************************************  Copyright (c) 1996 Artima Software Company. All Rights Reserved.  * Permission to use, copy, modify, and distribute this software  * and its documentation for EVALUATION purposes only  * is hereby granted provided that this copyright notice  * appears in all copies. "Evaluation purposes" are any uses which  * do not constitute the sale, sharing, or redistribution of this  * software with or to any other persons in any medium.  *  * ARTIMA SOFTWARE COMPANY MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT  * THE SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING  * BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS  * FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. ARTIMA SOFTWARE COMPANY  * SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF  * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.  PROJECT:  JavaWorld  MODULE:   Under The Hood  FILE:   CircleOfSquares.java  AUTHOR:   Bill Venners, August 1996  DESCRIPTION:  This file contains all the code for the java virtual machine simulation  applet, named Circle Of Squares, that accompanies the Under The Hood article  titled, "Floating Point Arithmetic".  As I developed this applet I had every class in a separate file. I combined  them in one file here to make it easier to download.  *********************************************************************/ import java.awt.BorderLayout; import java.awt.Button; import java.awt.Color; import java.awt.Component; import java.awt.Container; import java.awt.Dimension; import java.awt.Event; import java.awt.Font; import java.awt.GridLayout; import java.awt.Insets; import java.awt.Label; import java.awt.LayoutManager; import java.awt.Panel; public class CircleOfSquares extends java.applet.Applet {   // Vars for the three outer panels that are contained inside the Applet's   // panel.   // twoParts contains the stack and the method area. simulationController   // contains the Step and Reset buttons and the hint label.   private ThreeParts threeParts;   private RegisterPanel registers;   private ControlPanel simulationController;   // Local reference to reset button on control panel allows for easy enabling   // and   // disabling of this button.   private Button resetButton;   // Vars that implement the Java stack   private final int stackBase = 0x33330000;   private final int stackMemorySectionSize = 8;   private StackMemorySection stackMemorySection = new StackMemorySection(stackBase,       stackMemorySectionSize);   private StackMemoryView stackMemoryView;   // Vars that implement the method area of the JVM   private final int methodAreaBase = 0x44440000;   private MemorySection methodAreaMemorySection = new MemorySection(methodAreaBase,       SimData.methodAreaMemorySectionSize);   private MemoryView methodAreaMemoryView;   // Vars that implement the Java registers   private int pcRegister;   private int optopRegister;   private int frameRegister;   private int varsRegister;   public void init() {     setBackground(ColorTable.appletBackgroundColor);     setLayout(new BorderLayout(5, 5));     threeParts = new ThreeParts(SimData.methodAreaMemorySectionSize);     simulationController = new ControlPanel();     resetButton = simulationController.getResetButton();     ColoredLabel title = new ColoredLabel(StringTable.appletTitle, Label.CENTER,         ColorTable.titleColor);     title.setFont(new Font("Helvetica", Font.BOLD, 12));     add("North", title);     add("South", simulationController);     add("Center", threeParts);     // Get a reference to the UI objects that are actually manipulated by     // the handlers of the Step and Reset buttons. These aren't available     // without this explicit get() because these objects are buried several     // levels down in embedded panels.     stackMemoryView = threeParts.getStackMemoryViewReference();     methodAreaMemoryView = threeParts.getMethodAreaMemoryViewReference();     registers = threeParts.getRegisterPanel();     // Place the bytecodes into the method area     for (int i = 0; i < SimData.methodAreaMemorySectionSize; ++i) {       methodAreaMemorySection.setAtAddress(methodAreaBase + i, SimData.theProgram[i]);       methodAreaMemorySection.setLogicalValueAtAddress(methodAreaBase + i,           SimData.byteCodeMnemonics[i]);     }     ResetState();     UpdateStateDisplay();   }   public boolean action(Event evt, Object arg) {     if (evt.target instanceof Button) {       String bname = (String) arg;       if (bname.equals(StringTable.reset)) {         resetButton.disable();         ResetState();         UpdateStateDisplay();       } else if (bname.equals(StringTable.step)) {         if (!resetButton.isEnabled()) {           resetButton.enable();         }         ExecuteNextInstruction();         UpdateStateDisplay();       }     }     return true;   }   // ExecuteNextInstruction() grabs the instruction pointed to by the program   // counter, decodes it via the switch statement, and executes it by running   // the   // code under the appropriate case statement. The program counter is always   // set to the next instruction that should be executed, naturally. Only those   // bytecodes that appear in the short sequence presented in this simulation   // are interpreted here to save time (your time in downloading and my time   // in writing.)   void ExecuteNextInstruction() {     int a, b, result, i;     float fa, fb, fresult;     Float f;     int operand0, operand1;     int nextOpCode = methodAreaMemorySection.getAtAddress(pcRegister);     switch (nextOpCode) {     case OpCode.BIPUSH:       operand0 = methodAreaMemorySection.getAtAddress(pcRegister + 1);       stackMemorySection.setAtAddress(optopRegister, operand0);       stackMemorySection.setLogicalValueAtAddress(optopRegister, StringTable.operand);       optopRegister += 4;       pcRegister += 2;       break;     case OpCode.FCONST_0:       stackMemorySection.setAtAddress(optopRegister, Float.floatToIntBits((float) 0));       stackMemorySection.setLogicalValueAtAddress(optopRegister, "0");       optopRegister += 4;       ++pcRegister;       break;     case OpCode.FCONST_2:       stackMemorySection.setAtAddress(optopRegister, Float.floatToIntBits((float) 2));       stackMemorySection.setLogicalValueAtAddress(optopRegister, "2");       optopRegister += 4;       ++pcRegister;       break;     case OpCode.FLOAD_0:       a = stackMemorySection.getAtAddress(varsRegister);       stackMemorySection.setAtAddress(optopRegister, a);       fa = Float.intBitsToFloat(a);       stackMemorySection.setLogicalValueAtAddress(optopRegister, Float.toString(fa));       optopRegister += 4;       ++pcRegister;       break;     case OpCode.FMUL:       optopRegister -= 4;       a = stackMemorySection.getAtAddress(optopRegister);       fa = Float.intBitsToFloat(a);       stackMemorySection.setLogicalValueAtAddress(optopRegister, "");       optopRegister -= 4;       b = stackMemorySection.getAtAddress(optopRegister);       fb = Float.intBitsToFloat(b);       fresult = fa * fb;       result = Float.floatToIntBits(fresult);       stackMemorySection.setAtAddress(optopRegister, result);       stackMemorySection.setLogicalValueAtAddress(optopRegister, Float.toString(fresult));       optopRegister += 4;       ++pcRegister;       break;     case OpCode.FSTORE_0:       optopRegister -= 4;       a = stackMemorySection.getAtAddress(optopRegister);       stackMemorySection.setLogicalValueAtAddress(optopRegister, "");       stackMemorySection.setAtAddress(varsRegister, a);       fa = Float.intBitsToFloat(a);       stackMemorySection.setLogicalValueAtAddress(varsRegister, Float.toString(fa));       ++pcRegister;       break;     case OpCode.FSUB:       optopRegister -= 4;       a = stackMemorySection.getAtAddress(optopRegister);       fa = Float.intBitsToFloat(a);       stackMemorySection.setLogicalValueAtAddress(optopRegister, "");       optopRegister -= 4;       b = stackMemorySection.getAtAddress(optopRegister);       fb = Float.intBitsToFloat(b);       fresult = fb - fa;       result = Float.floatToIntBits(fresult);       stackMemorySection.setAtAddress(optopRegister, result);       stackMemorySection.setLogicalValueAtAddress(optopRegister, Float.toString(fresult));       optopRegister += 4;       ++pcRegister;       break;     case OpCode.GOTO:       operand1 = methodAreaMemorySection.getAtAddress(pcRegister + 1);       operand0 = methodAreaMemorySection.getAtAddress(pcRegister + 2);       int offset = (operand1 << 8) | (operand0 & 0xff);       pcRegister += offset;       break;     case OpCode.IADD:       optopRegister -= 4;       a = stackMemorySection.getAtAddress(optopRegister);       stackMemorySection.setLogicalValueAtAddress(optopRegister, "");       optopRegister -= 4;       b = stackMemorySection.getAtAddress(optopRegister);       result = a + b;       stackMemorySection.setAtAddress(optopRegister, result);       optopRegister += 4;       ++pcRegister;       break;     case OpCode.ICONST_M1:       stackMemorySection.setAtAddress(optopRegister, -1);       stackMemorySection.setLogicalValueAtAddress(optopRegister, StringTable.operand);       optopRegister += 4;       ++pcRegister;       break;     case OpCode.ICONST_0:       stackMemorySection.setAtAddress(optopRegister, 0);       stackMemorySection.setLogicalValueAtAddress(optopRegister, StringTable.operand);       optopRegister += 4;       ++pcRegister;       break;     case OpCode.ICONST_1:       stackMemorySection.setAtAddress(optopRegister, 1);       stackMemorySection.setLogicalValueAtAddress(optopRegister, StringTable.operand);       optopRegister += 4;       ++pcRegister;       break;     case OpCode.ICONST_2:       stackMemorySection.setAtAddress(optopRegister, 2);       stackMemorySection.setLogicalValueAtAddress(optopRegister, StringTable.operand);       optopRegister += 4;       ++pcRegister;       break;     case OpCode.IINC:       operand0 = methodAreaMemorySection.getAtAddress(pcRegister + 1);       operand1 = methodAreaMemorySection.getAtAddress(pcRegister + 2);       a = stackMemorySection.getAtAddress(varsRegister + (operand0 * 4));       a += operand1;       stackMemorySection.setAtAddress(varsRegister + (operand0 * 4), a);       pcRegister += 3;       break;     case OpCode.ILOAD_0:       a = stackMemorySection.getAtAddress(varsRegister);       stackMemorySection.setAtAddress(optopRegister, a);       stackMemorySection.setLogicalValueAtAddress(optopRegister, StringTable.operand);       optopRegister += 4;       ++pcRegister;       break;     case OpCode.ILOAD_1:       a = stackMemorySection.getAtAddress(varsRegister + 4);       stackMemorySection.setAtAddress(optopRegister, a);       stackMemorySection.setLogicalValueAtAddress(optopRegister, StringTable.operand);       optopRegister += 4;       ++pcRegister;       break;     case OpCode.IMUL:       optopRegister -= 4;       a = stackMemorySection.getAtAddress(optopRegister);       stackMemorySection.setLogicalValueAtAddress(optopRegister, "");       optopRegister -= 4;       b = stackMemorySection.getAtAddress(optopRegister);       result = a * b;       stackMemorySection.setAtAddress(optopRegister, result);       optopRegister += 4;       ++pcRegister;       break;     case OpCode.INT2BYTE:       a = stackMemorySection.getAtAddress(optopRegister - 4);       a = (byte) a;       stackMemorySection.setAtAddress(optopRegister - 4, a);       stackMemorySection.setLogicalValueAtAddress(optopRegister - 4, StringTable.operand);       ++pcRegister;       break;     case OpCode.ISTORE_0:       optopRegister -= 4;       a = stackMemorySection.getAtAddress(optopRegister);       stackMemorySection.setLogicalValueAtAddress(optopRegister, "");       stackMemorySection.setAtAddress(varsRegister, a);       ++pcRegister;       break;     case OpCode.ISTORE_1:       optopRegister -= 4;       a = stackMemorySection.getAtAddress(optopRegister);       stackMemorySection.setLogicalValueAtAddress(optopRegister + 4, "");       stackMemorySection.setAtAddress(varsRegister + 4, a);       ++pcRegister;       break;     }   }   // Pushing the Reset button will cause ResetState() to be executed, which will   // reset all the data to its initial values.   void ResetState() {     pcRegister = methodAreaBase;     optopRegister = stackBase + SimData.optopOffset;     frameRegister = stackBase + SimData.frameOffset;     varsRegister = stackBase;     int i;     for (i = 0; i < 7; ++i) {       stackMemorySection.setLogicalValueAtAddress(stackBase + (i * 4), "");       stackMemorySection.setAtAddress(stackBase + (i * 4), 0);     }     methodAreaMemoryView.update(methodAreaMemorySection, methodAreaBase);   }   // UpdateStateDisplay writes the current state of the JVM to the UI.   void UpdateStateDisplay() {     registers.setPcRegister(pcRegister);     registers.setOptopRegister(optopRegister);     registers.setFrameRegister(frameRegister);     registers.setVarsRegister(varsRegister);     stackMemoryView.update(stackMemorySection, stackBase);     methodAreaMemoryView.updateProgramCounter(pcRegister - methodAreaBase, methodAreaMemorySection);     stackMemoryView.clearPointers();     stackMemoryView.updatePointer((varsRegister - stackBase) / 4, StringTable.varsPointer);     stackMemoryView.updatePointer((frameRegister - stackBase) / 4, StringTable.framePointer);     stackMemoryView.updatePointer((optopRegister - stackBase) / 4, StringTable.optopPointer);     int nextOpCode = methodAreaMemorySection.getAtAddress(pcRegister);     switch (nextOpCode) {     case OpCode.BIPUSH:       simulationController.setExplanationText(StringTable.bipushText);       break;     case OpCode.FCONST_0:       simulationController.setExplanationText(StringTable.fconst_0Text);       break;     case OpCode.FCONST_2:       simulationController.setExplanationText(StringTable.fconst_2Text);       break;     case OpCode.FLOAD_0:       simulationController.setExplanationText(StringTable.fload_0Text);       break;     case OpCode.FMUL:       simulationController.setExplanationText(StringTable.fmulText);       break;     case OpCode.FSTORE_0:       simulationController.setExplanationText(StringTable.fstore_0Text);       break;     case OpCode.FSUB:       simulationController.setExplanationText(StringTable.fsubText);       break;     case OpCode.GOTO:       simulationController.setExplanationText(StringTable.gotoText);       break;     case OpCode.IADD:       simulationController.setExplanationText(StringTable.iaddText);       break;     case OpCode.ICONST_M1:       simulationController.setExplanationText(StringTable.iconst_m1Text);       break;     case OpCode.ICONST_0:       simulationController.setExplanationText(StringTable.iconst_0Text);       break;     case OpCode.ICONST_1:       simulationController.setExplanationText(StringTable.iconst_1Text);       break;     case OpCode.ICONST_2:       simulationController.setExplanationText(StringTable.iconst_2Text);       break;     case OpCode.IINC:       simulationController.setExplanationText(StringTable.iincText);       break;     case OpCode.ILOAD_0:       simulationController.setExplanationText(StringTable.iload_0Text);       break;     case OpCode.ILOAD_1:       simulationController.setExplanationText(StringTable.iload_1Text);       break;     case OpCode.IMUL:       simulationController.setExplanationText(StringTable.imulText);       break;     case OpCode.INT2BYTE:       simulationController.setExplanationText(StringTable.int2byteText);       break;     case OpCode.ISTORE_0:       simulationController.setExplanationText(StringTable.istore_0Text);       break;     case OpCode.ISTORE_1:       simulationController.setExplanationText(StringTable.istore_1Text);       break;     default:       simulationController.setExplanationText("");       break;     }   }   // Make pretty border around entire applet panel   public Insets insets() {     return new Insets(5, 5, 5, 5);   } } // I used this class because I can't seem to set the background color of // a label. I only want a label, but I want the backgound to be gray. class ColoredLabel extends Panel {   private Label theLabel;   ColoredLabel(String label, int alignment, Color color) {     setLayout(new GridLayout(1, 1));     setBackground(color);     theLabel = new Label(label, alignment);     add(theLabel);   }   public void setLabelText(String s) {     theLabel.setText(s);   }   public Insets insets() {     return new Insets(0, 0, 0, 0);   } } class ColorTable {   static final Color appletBackgroundColor = Color.blue;   static final Color registersAreaColor = Color.magenta;   static final Color stackAreaColor = Color.magenta;   static final Color methodAreaColor = Color.magenta;   static final Color titleColor = Color.cyan;   static final Color explanationLabel = Color.cyan; } class ControlPanel extends Panel {   private ColoredLabel explanationLabel;   private GrayButton resetButton = new GrayButton(StringTable.reset);   ControlPanel() {     setLayout(new BorderLayout(5, 5));     Panel leftButtonPanel = new Panel();     leftButtonPanel.setLayout(new GridLayout(2, 1, 0, 5));     leftButtonPanel.add(new GrayButton(StringTable.step));     resetButton.disable();     leftButtonPanel.add(resetButton);     explanationLabel = new ColoredLabel("This is where the explanation goes...", Label.CENTER,         Color.lightGray);     explanationLabel.setBackground(ColorTable.explanationLabel);     Font plainFont = new Font("TimesRoman", Font.ITALIC, 12);     explanationLabel.setFont(plainFont);     add("West", leftButtonPanel);     add("Center", explanationLabel);   }   public void setExplanationText(String explanation) {     explanationLabel.setLabelText(explanation);   }   public Button getResetButton() {     return resetButton;   }   public Insets insets() {     // top, left, bottom, right     return new Insets(0, 0, 0, 0);   } } class GrayButton extends Button {   GrayButton(String label) {     super(label);     setBackground(Color.lightGray);   } } // GridSnapLayout lays out components in a grid that can have columns of // varying width. This is not a very general purpose layout manager. It // solves the specific problem of getting all the information I want to display // about // the stack and method areas in a nice grid. Because some columns of info need // more room than others, and space is limited on a web page, I needed to be // able to specify varying widths of columns in a grid. class GridSnapLayout implements LayoutManager {   // rows and cols are the number of rows and columns of the grid upon   // which the components are placed. Components are always one row   // in height, but may be more than one column in width. The number   // of columns width of each component is stored in hComponentCellWidths.   // The array length of hComponentCellWidths indicates the number of   // components that will appear on each row.   private int rows;   private int cols;   private int[] hComponentCellWidths;   public GridSnapLayout(int rows, int cols, int[] hComponentCellWidths) {     this.rows = rows;     this.cols = cols;     this.hComponentCellWidths = hComponentCellWidths;   }   public void addLayoutComponent(String name, Component comp) {   }   public void removeLayoutComponent(Component comp) {   }   // Calculate preferred size as if each component were taking an equal   // share of the width of a row.   public Dimension preferredLayoutSize(Container parent) {     int rowCount = rows;     int colCount = cols;     Insets parentInsets = parent.insets();     int componentCount = parent.countComponents();     if (rowCount > 0) {       colCount = (componentCount + rowCount - 1) / rowCount;     } else {       rowCount = (componentCount + colCount - 1) / colCount;     }     // Find the maximum preferred width and the maximum preferred height     // of any component.     int w = 0;     int h = 0;     for (int i = 0; i < componentCount; i++) {       Component comp = parent.getComponent(i);       Dimension d = comp.preferredSize();       if (w < d.width) {         w = d.width;       }       if (h < d.height) {         h = d.height;       }     }     // Return the maximum preferred component width and height times the number     // of columns and rows, respectively, plus any insets in the parent.     return new Dimension(parentInsets.left + parentInsets.right + colCount * w, parentInsets.top         + parentInsets.bottom + rowCount * h);   }   // Calculate minimum size as if each component were taking an equal   // share of the width of a row.   public Dimension minimumLayoutSize(Container parent) {     Insets parentInsets = parent.insets();     int componentCount = parent.countComponents();     int rowCount = rows;     int colCount = cols;     if (rowCount > 0) {       colCount = (componentCount + rowCount - 1) / rowCount;     } else {       rowCount = (componentCount + colCount - 1) / colCount;     }     // Find the maximum "minimum width" and the maximum "minimum height"     // of any component.     int w = 0;     int h = 0;     for (int i = 0; i < componentCount; i++) {       Component comp = parent.getComponent(i);       Dimension d = comp.minimumSize();       if (w < d.width) {         w = d.width;       }       if (h < d.height) {         h = d.height;       }     }     // Return the maximum "minimum component width and height" times the number     // of columns and rows, respectively, plus any insets in the parent.     return new Dimension(parentInsets.left + parentInsets.right + colCount * w, parentInsets.top         + parentInsets.bottom + rowCount * h);   }   // Layout the container such that the widths of columns correspond   // to the number of columns in that components hComponentCellWidth   // array element. For example, if the   public void layoutContainer(Container parent) {     int rowCount = rows;     int colCount = hComponentCellWidths.length;     Insets parentInsets = parent.insets();     int componentCount = parent.countComponents();     if (componentCount == 0) {       return;     }     // Calculate the width and height of each grid cell. The height will     // be the height of each component, but the width may not. The width     // of a component will be some multiple of a grid cell width. The     // number of grid cells for each component is defined by the     // hComponentCellWidths array. w is width of each grid cell. h is     // height of each grid cell.     Dimension parentDim = parent.size();     int w = parentDim.width - (parentInsets.left + parentInsets.right);     int h = parentDim.height - (parentInsets.top + parentInsets.bottom);     w /= cols;     h /= rowCount;     // For each row and column of components (not grid cells) position     // the component.     for (int c = 0, x = parentInsets.left; c < colCount; c++) {       for (int r = 0, y = parentInsets.top; r < rowCount; r++) {         int i = r * colCount + c;         if (i < componentCount) {           parent.getComponent(i).reshape(x, y, w * hComponentCellWidths[c], h);         }         y += h;       }       x += (w * hComponentCellWidths[c]);     }   } } class HexString {   private final String hexChar = "0123456789abcdef";   private StringBuffer buf = new StringBuffer();   void Convert(int val, int maxNibblesToConvert) {     buf.setLength(0);     int v = val;     for (int i = 0; i < maxNibblesToConvert; ++i) {       if (v == 0) {         if (i == 0) {           buf.insert(0, '0');         }         break;       }       // Get lowest nibble       int remainder = v & 0xf;       // Convert nibble to a character and insert it into the beginning of the       // string       buf.insert(0, hexChar.charAt(remainder));       // Shift the int to the right four bits       v >>>= 4;     }   }   HexString(int val, int minWidth) {     Convert(val, minWidth);     int charsNeeded = minWidth - buf.length();     for (int i = 0; i < charsNeeded; ++i) {       buf.insert(0, '0');     }   }   public String getString() {     return buf.toString();   } } class LabeledRegister extends Panel {   private ColoredLabel registerContents;   LabeledRegister(String labelText) {     setLayout(new BorderLayout(5, 5));     registerContents = new ColoredLabel("00000000", Label.CENTER, Color.lightGray);     registerContents.setFont(new Font("TimesRoman", Font.PLAIN, 11));     Label title = new Label(labelText, Label.RIGHT);     title.setFont(new Font("Helvetica", Font.ITALIC, 11));     add("East", registerContents);     add("Center", title);   }   public void setRegister(int val) {     HexString hexString = new HexString(val, 8);     registerContents.setLabelText(hexString.getString());   }   public Insets insets() {     return new Insets(0, 0, 0, 0);   } } // MemorySection is just used for the method area in this applet. This // implements // the functionality of the method area and has nothing to do with the UI. class MemorySection {   private int[] memory;   private int baseAddress;   private String[] logicalValueString;   MemorySection(int base, int size) {     baseAddress = base;     memory = new int[size];     logicalValueString = new String[size];     for (int i = 0; i < size; ++i) {       logicalValueString[i] = new String();     }   }   int getBaseAddress() {     return baseAddress;   }   public int getAtAddress(int address) {     return memory[address - baseAddress];   }   public String getLogicalValueAtAddress(int address) {     return logicalValueString[address - baseAddress];   }   public void setAtAddress(int address, int value) {     memory[address - baseAddress] = value;   }   public void setLogicalValueAtAddress(int address, String s) {     logicalValueString[address - baseAddress] = s;   }   int getSize() {     return memory.length;   } } // MemoryView is just used for the method area in this applet. It implements the // UI of the method area. class MemoryView extends Panel {   private final int memoryLocationsVisibleCount = SimData.methodAreaMemoryLocationsVisibleCount;   private Label[] pointer = new Label[memoryLocationsVisibleCount];   private Label[] address = new Label[memoryLocationsVisibleCount];   private Label[] byteValue = new Label[memoryLocationsVisibleCount];   private Label[] logicalValue = new Label[memoryLocationsVisibleCount];   private int firstVisibleRow;   private int currentProgramCounterRow;   MemoryView(int methodAreaMemSectionSize) {     setLayout(new GridLayout(memoryLocationsVisibleCount, 4));     setBackground(Color.lightGray);     Font plainFont = new Font("TimesRoman", Font.PLAIN, 11);     setFont(plainFont);     Font italicFont = new Font("TimesRoman", Font.ITALIC, 11);     for (int i = 0; i < memoryLocationsVisibleCount; ++i) {       pointer[i] = new Label("", Label.RIGHT);       pointer[i].setFont(italicFont);       add(pointer[i]);       address[i] = new Label("", Label.CENTER);       add(address[i]);       byteValue[i] = new Label("", Label.CENTER);       add(byteValue[i]);       logicalValue[i] = new Label("", Label.LEFT);       add(logicalValue[i]);     }   }   public void setAt(int i, int addressValue, int value, String logicalValueStr) {     HexString addressValueHexString = new HexString(addressValue, 8);     HexString byteValueHexString = new HexString(value, 2);     address[i].setText(addressValueHexString.getString());     byteValue[i].setText(byteValueHexString.getString());     logicalValue[i].setText(logicalValueStr);   }   public void update(MemorySection memorySection, int initialAddress) {     for (int i = 0; i < memoryLocationsVisibleCount; ++i) {       int theByte = memorySection.getAtAddress(initialAddress + i);       String logicalValue = memorySection.getLogicalValueAtAddress(initialAddress + i);       setAt(i, initialAddress + i, theByte, logicalValue);     }   }   public void clearPointers() {     for (int i = 0; i < memoryLocationsVisibleCount; ++i) {       pointer[i].setText("");     }   }   public void updateProgramCounter(int i, MemorySection memorySection) {     pointer[currentProgramCounterRow - firstVisibleRow].setText("");     if (i - firstVisibleRow >= memoryLocationsVisibleCount) {       firstVisibleRow += 5;       if (firstVisibleRow > memorySection.getSize() - memoryLocationsVisibleCount) {         firstVisibleRow = memorySection.getSize() - memoryLocationsVisibleCount;       }       update(memorySection, memorySection.getBaseAddress() + firstVisibleRow);     } else if (i < firstVisibleRow) {       firstVisibleRow = i;       update(memorySection, memorySection.getBaseAddress() + firstVisibleRow);     }     pointer[i - firstVisibleRow].setText("pc >");     currentProgramCounterRow = i;   }   public Insets insets() {     // top, left, bottom, right     return new Insets(0, 0, 0, 0);   } } class MemoryViewTitlePanel extends Panel {   MemoryViewTitlePanel() {     setLayout(new GridLayout(1, 4));     setFont(new Font("Helvetica", Font.ITALIC, 11));     add(new Label("", Label.CENTER));     add(new Label(StringTable.address, Label.CENTER));     add(new Label(StringTable.bytecodes, Label.CENTER));     add(new Label(StringTable.mnemonics, Label.CENTER));   }   public Insets insets() {     // top, left, bottom, right     return new Insets(0, 0, 0, 0);   } } class MemoryViewWithTitles extends Panel {   private MemoryView memoryView;   MemoryViewWithTitles(int methodAreaMemorySectionSize) {     memoryView = new MemoryView(methodAreaMemorySectionSize);     setLayout(new BorderLayout());     add("North", new MemoryViewTitlePanel());     add("Center", memoryView);   }   public MemoryView getMemoryViewReference() {     return memoryView;   }   public Insets insets() {     // top, left, bottom, right     return new Insets(0, 0, 0, 0);   } } class MethodAreaPanel extends Panel {   private Label title;   private MemoryViewWithTitles memoryView;   MethodAreaPanel(int methodAreaMemorySectionSize) {     memoryView = new MemoryViewWithTitles(methodAreaMemorySectionSize);     setLayout(new BorderLayout());     title = new Label("Method Area", Label.CENTER);     title.setFont(new Font("Helvetica", Font.BOLD, 11));     add("North", title);     add("Center", memoryView);   }   public MemoryView getMemoryViewReference() {     return memoryView.getMemoryViewReference();   }   public Insets insets() {     return new Insets(5, 5, 5, 5);   } } class OpCode {   final static int NOP = 0;   final static int ACONST_NULL = 1;   final static int ICONST_M1 = 2;   final static int ICONST_0 = 3;   final static int ICONST_1 = 4;   final static int ICONST_2 = 5;   final static int ICONST_3 = 6;   final static int ICONST_4 = 7;   final static int ICONST_5 = 8;   final static int LCONST_0 = 9;   final static int LCONST_1 = 10;   final static int FCONST_0 = 11;   final static int FCONST_1 = 12;   final static int FCONST_2 = 13;   final static int DCONST_0 = 14;   final static int DCONST_1 = 15;   final static int BIPUSH = 16;   final static int SIPUSH = 17;   final static int LDC1 = 18;   final static int LDC2 = 19;   final static int LDC2W = 20;   final static int ILOAD = 21;   final static int LLOAD = 22;   final static int FLOAD = 23;   final static int DLOAD = 24;   final static int ALOAD = 25;   final static int ILOAD_0 = 26;   final static int ILOAD_1 = 27;   final static int ILOAD_2 = 28;   final static int ILOAD_3 = 29;   final static int LLOAD_0 = 30;   final static int LLOAD_1 = 31;   final static int LLOAD_2 = 32;   final static int LLOAD_3 = 33;   final static int FLOAD_0 = 34;   final static int FLOAD_1 = 35;   final static int FLOAD_2 = 36;   final static int FLOAD_3 = 37;   final static int DLOAD_0 = 38;   final static int DLOAD_1 = 39;   final static int DLOAD_2 = 40;   final static int DLOAD_3 = 41;   final static int ALOAD_0 = 42;   final static int ALOAD_1 = 43;   final static int ALOAD_2 = 44;   final static int ALOAD_3 = 45;   final static int IALOAD = 46;   final static int LALOAD = 47;   final static int FALOAD = 48;   final static int DALOAD = 49;   final static int AALOAD = 50;   final static int BALOAD = 51;   final static int CALOAD = 52;   final static int SALOAD = 53;   final static int ISTORE = 54;   final static int LSTORE = 55;   final static int FSTORE = 56;   final static int DSTORE = 57;   final static int ASTORE = 58;   final static int ISTORE_0 = 59;   final static int ISTORE_1 = 60;   final static int ISTORE_2 = 61;   final static int ISTORE_3 = 62;   final static int LSTORE_0 = 63;   final static int LSTORE_1 = 64;   final static int LSTORE_2 = 65;   final static int LSTORE_3 = 66;   final static int FSTORE_0 = 67;   final static int FSTORE_1 = 68;   final static int FSTORE_2 = 69;   final static int FSTORE_3 = 70;   final static int DSTORE_0 = 71;   final static int DSTORE_1 = 72;   final static int DSTORE_2 = 73;   final static int DSTORE_3 = 74;   final static int ASTORE_0 = 75;   final static int ASTORE_1 = 76;   final static int ASTORE_2 = 77;   final static int ASTORE_3 = 78;   final static int IASTORE = 79;   final static int LASTORE = 80;   final static int FASTORE = 81;   final static int DASTORE = 82;   final static int AASTORE = 83;   final static int BASTORE = 84;   final static int CASTORE = 85;   final static int SASTORE = 86;   final static int POP = 87;   final static int POP2 = 88;   final static int DUP = 89;   final static int DUP_X1 = 90;   final static int DUP_X2 = 91;   final static int DUP2 = 92;   final static int DUP2_X1 = 93;   final static int DUP2_X2 = 94;   final static int SWAP = 95;   final static int IADD = 96;   final static int LADD = 97;   final static int FADD = 98;   final static int DADD = 99;   final static int ISUB = 100;   final static int LSUB = 101;   final static int FSUB = 102;   final static int DSUB = 103;   final static int IMUL = 104;   final static int LMUL = 105;   final static int FMUL = 106;   final static int DMUL = 107;   final static int IDIV = 108;   final static int LDIV = 109;   final static int FDIV = 110;   final static int DDIV = 111;   final static int IREM = 112;   final static int LREM = 113;   final static int FREM = 114;   final static int DREM = 115;   final static int INEG = 116;   final static int LNEG = 117;   final static int FNEG = 118;   final static int DNEG = 119;   final static int ISHL = 120;   final static int LSHL = 121;   final static int ISHR = 122;   final static int LSHR = 123;   final static int IUSHR = 124;   final static int LUSHR = 125;   final static int IAND = 126;   final static int LAND = 127;   final static int IOR = 128;   final static int LOR = 129;   final static int IXOR = 130;   final static int LXOR = 131;   final static int IINC = 132;   final static int I2L = 133;   final static int I2F = 134;   final static int I2D = 135;   final static int L2I = 136;   final static int L2F = 137;   final static int L2D = 138;   final static int F2I = 139;   final static int F2L = 140;   final static int F2D = 141;   final static int D2I = 142;   final static int D2L = 143;   final static int D2F = 144;   final static int INT2BYTE = 145;   final static int INT2CHAR = 146;   final static int INT2SHORT = 147;   final static int LCMP = 148;   final static int FCMPL = 149;   final static int FCMPG = 150;   final static int DCMPL = 151;   final static int DCMPG = 152;   final static int IFEQ = 153;   final static int IFNE = 154;   final static int IFLT = 155;   final static int IFGE = 156;   final static int IFGT = 157;   final static int IFLE = 158;   final static int IF_ICMPEQ = 159;   final static int IF_ICMPNE = 160;   final static int IF_ICMPLT = 161;   final static int IF_ICMPGT = 163;   final static int IF_ICMPLE = 164;   final static int IF_ICMPGE = 162;   final static int IF_ACMPEQ = 165;   final static int IF_ACMPNE = 166;   final static int GOTO = 167;   final static int JSR = 168;   final static int RET = 169;   final static int TABLESWITCH = 170;   final static int LOOKUPSWITCH = 171;   final static int IRETURN = 172;   final static int LRETURN = 173;   final static int FRETURN = 174;   final static int DRETURN = 175;   final static int ARETURN = 176;   final static int RETURN = 177;   final static int INVOKEVIRTUAL = 182;   final static int INVOKENONVIRTUAL = 183;   final static int INVOKESTATIC = 184;   final static int INVOKEINTERFACE = 185;   final static int NEW = 187;   final static int NEWARRAY = 188;   final static int ANEWARRAY = 189;   final static int ARRAYLENGTH = 190;   final static int ATHROW = 191;   final static int CHECKCAST = 192;   final static int INSTANCEOF = 193;   final static int MONITORENTER = 194;   final static int MONITOREXIT = 195;   final static int WIDE = 196;   final static int MULTIANEWARRAY = 197;   final static int IFNULL = 198;   final static int IFNONNULL = 199;   final static int GOTO_W = 200;   final static int JSR_W = 201;   final static int BREAKPOINT = 202;   final static int RET_W = 209; } class PanelWithInsets extends Panel {   private int top;   private int left;   private int bottom;   private int right;   PanelWithInsets(int t, int l, int b, int r) {     top = t;     left = l;     bottom = b;     right = r;   }   PanelWithInsets() {     top = 5;     left = 5;     bottom = 5;     right = 5;   }   public Insets insets() {     return new Insets(top, left, bottom, right);   } } class RegisterPanel extends Panel {   private LabeledRegister pcRegister;   private LabeledRegister optopRegister;   private LabeledRegister frameRegister;   private LabeledRegister varsRegister;   RegisterPanel() {     setLayout(new BorderLayout(5, 5));     pcRegister = new LabeledRegister(StringTable.pc);     optopRegister = new LabeledRegister(StringTable.optop);     frameRegister = new LabeledRegister(StringTable.frame);     varsRegister = new LabeledRegister(StringTable.vars);     setBackground(ColorTable.registersAreaColor);     Panel labeledRegisterPanel = new Panel();     labeledRegisterPanel.setLayout(new GridLayout(1, 4, 5, 5));     labeledRegisterPanel.add(pcRegister);     labeledRegisterPanel.add(optopRegister);     labeledRegisterPanel.add(frameRegister);     labeledRegisterPanel.add(varsRegister);     Label title = new Label(StringTable.Registers, Label.CENTER);     title.setFont(new Font("Helvetica", Font.BOLD, 11));     add("West", title);     add("Center", labeledRegisterPanel);   }   public void setPcRegister(int val) {     pcRegister.setRegister(val);   }   public void setOptopRegister(int val) {     optopRegister.setRegister(val);   }   public void setFrameRegister(int val) {     frameRegister.setRegister(val);   }   public void setVarsRegister(int val) {     varsRegister.setRegister(val);   }   public Insets insets() {     // top, left, bottom, right     return new Insets(5, 5, 5, 5);   } } class RepeaterButton extends GrayButton {   RepeaterButton(String label) {     super(label);   } } class SimData {   static final int methodAreaMemorySectionSize = 13;   static final int methodAreaMemoryLocationsVisibleCount = 13;   static final int frameOffset = 4;   static final int optopOffset = 16;   static int[] theProgram = { OpCode.FCONST_2, OpCode.FSTORE_0, OpCode.FLOAD_0, OpCode.FLOAD_0,       OpCode.FMUL, OpCode.FSTORE_0, OpCode.FCONST_0, OpCode.FLOAD_0, OpCode.FSUB, OpCode.FSTORE_0,       OpCode.GOTO, (byte) 0xff, (byte) 0xf8 };   static String[] byteCodeMnemonics = { "fconst_2", "fstore_0", "fload_0", "fload_0", "fmul",       "fstore_0", "fconst_0", "fload_0", "fsub", "fstore_0", "goto -17", "", "" }; } // StackMemorySection is just used for the stack in this applet. This implements // the functionality of the stack and has nothing to do with the UI. class StackMemorySection {   private int[] memory;   private int baseAddress;   private String[] logicalValueString;   StackMemorySection(int base, int size) {     baseAddress = base;     memory = new int[size];     logicalValueString = new String[size];     for (int i = 0; i < size; ++i) {       memory[i] = 0;       logicalValueString[i] = new String();     }   }   public int getAtAddress(int address) {     return memory[(address - baseAddress) / 4];   }   public String getLogicalValueAtAddress(int address) {     return logicalValueString[(address - baseAddress) / 4];   }   public void setAtAddress(int address, int value) {     memory[(address - baseAddress) / 4] = value;   }   public void setLogicalValueAtAddress(int address, String s) {     logicalValueString[(address - baseAddress) / 4] = s;   } } // StackMemoryView is just used for the stack in this applet. It implements the // UI of the stack. class StackMemoryView extends Panel {   private final int memoryLocationsVisibleCount = 8;   private Label[] pointer = new Label[memoryLocationsVisibleCount];   private Label[] address = new Label[memoryLocationsVisibleCount];   private Label[] wordValue = new Label[memoryLocationsVisibleCount];   private Label[] logicalValue = new Label[memoryLocationsVisibleCount];   StackMemoryView() {     int[] hComponentCellWidths = new int[4];     hComponentCellWidths[0] = 2;     hComponentCellWidths[1] = 2;     hComponentCellWidths[2] = 2;     hComponentCellWidths[3] = 3;     setLayout(new GridSnapLayout(memoryLocationsVisibleCount, 9, hComponentCellWidths));     setBackground(Color.lightGray);     Font plainFont = new Font("TimesRoman", Font.PLAIN, 11);     setFont(plainFont);     Font italicFont = new Font("TimesRoman", Font.ITALIC, 11);     for (int i = memoryLocationsVisibleCount - 1; i >= 0; --i) {       pointer[i] = new Label("", Label.RIGHT);       pointer[i].setFont(italicFont);       add(pointer[i]);       address[i] = new Label("", Label.CENTER);       add(address[i]);       wordValue[i] = new Label("", Label.CENTER);       add(wordValue[i]);       logicalValue[i] = new Label("", Label.CENTER);       add(logicalValue[i]);     }   }   public void setAt(int i, int addressValue, int value, String logicalValueString) {     HexString addressValueString = new HexString(addressValue, 8);     HexString wordValueString = new HexString(value, 8);     address[memoryLocationsVisibleCount - 1 - i].setText(addressValueString.getString());     wordValue[memoryLocationsVisibleCount - 1 - i].setText(wordValueString.getString());     logicalValue[memoryLocationsVisibleCount - 1 - i].setText(logicalValueString);   }   public void update(StackMemorySection memorySection, int initialAddress) {     for (int i = 0; i < memoryLocationsVisibleCount; ++i) {       int theWord = memorySection.getAtAddress(initialAddress + (i * 4));       String logicalValue = memorySection.getLogicalValueAtAddress(initialAddress + (i * 4));       setAt(i, initialAddress + (i * 4), theWord, logicalValue);     }   }   public void clearPointers() {     for (int i = 0; i < memoryLocationsVisibleCount; ++i) {       pointer[i].setText("");     }   }   public void updatePointer(int i, String pointerString) {     pointer[memoryLocationsVisibleCount - 1 - i].setText(pointerString);   }   public Insets insets() {     // top, left, bottom, right     return new Insets(0, 0, 0, 0);   } } class StackMemoryViewTitlePanel extends Panel {   StackMemoryViewTitlePanel() {     // setLayout(new GridLayout(1, 4));     int[] hComponentCellWidths = new int[4];     hComponentCellWidths[0] = 2;     hComponentCellWidths[1] = 2;     hComponentCellWidths[2] = 2;     hComponentCellWidths[3] = 3;     setLayout(new GridSnapLayout(1, 9, hComponentCellWidths));     setFont(new Font("Helvetica", Font.ITALIC, 11));     add(new Label("", Label.CENTER));     add(new Label(StringTable.address, Label.CENTER));     add(new Label(StringTable.hexValue, Label.CENTER));     add(new Label(StringTable.value, Label.CENTER));   }   public Insets insets() {     // top, left, bottom, right     return new Insets(0, 0, 0, 0);   } } class StackMemoryViewWithTitles extends Panel {   private StackMemoryView memoryView = new StackMemoryView();   StackMemoryViewWithTitles() {     setLayout(new BorderLayout());     add("North", new StackMemoryViewTitlePanel());     add("Center", memoryView);   }   public StackMemoryView getMemoryViewReference() {     return memoryView;   }   public Insets insets() {     // top, left, bottom, right     return new Insets(0, 0, 0, 0);   } } class StackPanel extends Panel {   private Label title;   private StackMemoryViewWithTitles memoryView = new StackMemoryViewWithTitles();   StackPanel() {     setLayout(new BorderLayout());     title = new Label("Stack", Label.CENTER);     title.setFont(new Font("Helvetica", Font.BOLD, 11));     add("North", title);     add("Center", memoryView);   }   public StackMemoryView getMemoryViewReference() {     return memoryView.getMemoryViewReference();   }   public Insets insets() {     return new Insets(5, 5, 5, 5);   } } class StringTable {   public final static String appletTitle = "CIRCLE OF SQUARES";   public final static String step = "Step";   public final static String reset = "Reset";   public final static String operand = "operand";   public final static String execEnv = "exec env";   public final static String localVars = "local vars";   public final static String varsPointer = "vars >";   public final static String framePointer = "frame >";   public final static String optopPointer = "optop >";   public final static String address = "address";   public final static String bytecodes = "bytecodes";   public final static String mnemonics = "mnemonics";   public final static String hexValue = "hex value";   public final static String value = "value";   public final static String Registers = "Registers";   public final static String pc = "pc";   public final static String optop = "optop";   public final static String frame = "frame";   public final static String vars = "vars";   public final static String bipushText = "bipush will expand the next byte to an int and push it onto the stack.";   public final static String fconst_0Text = "fconst_0 will push float 0.0 onto the stack.";   public final static String fconst_2Text = "fconst_2 will push float 2.0 onto the stack.";   public final static String fload_0Text = "fload_0 will push the float at local variable 0 onto the stack.";   public final static String fmulText = "fmul will pop two floats, multiply them, and push the result.";   public final static String fstore_0Text = "fstore_0 will pop the float off the top of the stack and store it in local variable 0.";   public final static String fsubText = "fsub will pop two floats, subtract them, and push the result.";   public final static String gotoText = "goto will cause a jump to the specified offset.";   public final static String iaddText = "iadd will pop the top two integers off the stack, add them, and push the result back onto the stack.";   public final static String iconst_m1Text = "iconst_m1 will push -1 onto the stack.";   public final static String iconst_0Text = "iconst_0 will push 0 onto the stack.";   public final static String iconst_1Text = "iconst_1 will push 1 onto the stack.";   public final static String iconst_2Text = "iconst_2 will push 2 onto the stack.";   public final static String iincText = "iinc will increment the specified local variable by the specified amount.";   public final static String iload_0Text = "iload_0 will push the integer at local variable 0 onto the stack.";   public final static String iload_1Text = "iload_1 will push the integer at local variable 1 onto the stack.";   public final static String imulText = "imul will pop two integers, multiply them, and push the result.";   public final static String int2byteText = "int2byte will convert the topmost int on the stack to a value valid for the byte type.";   public final static String istore_0Text = "istore_0 will pop the integer off the top of the stack and store it in local variable 0.";   public final static String istore_1Text = "istore_1 will pop the integer off the top of the stack and store it in local variable 1."; } class ThreeParts extends Panel {   private RegisterPanel registers;   private TwoParts twoParts;   ThreeParts(int methodAreaMemorySectionSize) {     setLayout(new BorderLayout(5, 5));     registers = new RegisterPanel();     twoParts = new TwoParts(methodAreaMemorySectionSize);     add("North", registers);     add("Center", twoParts);   }   StackMemoryView getStackMemoryViewReference() {     return twoParts.getStackMemoryViewReference();   }   MemoryView getMethodAreaMemoryViewReference() {     return twoParts.getMethodAreaMemoryViewReference();   }   RegisterPanel getRegisterPanel() {     return registers;   } } // TwoParts is the panel that contains the Stack and Method Area panels class TwoParts extends Panel {   private StackPanel stack;   private MethodAreaPanel methodArea;   TwoParts(int methodAreaMemorySectionSize) {     setLayout(new GridLayout(1, 2, 5, 5));     stack = new StackPanel();     methodArea = new MethodAreaPanel(methodAreaMemorySectionSize);     stack.setBackground(ColorTable.stackAreaColor);     methodArea.setBackground(ColorTable.methodAreaColor);     add(stack);     add(methodArea);   }   public StackMemoryView getStackMemoryViewReference() {     return stack.getMemoryViewReference();   }   public MemoryView getMethodAreaMemoryViewReference() {     return methodArea.getMemoryViewReference();   }   // top, left, bottom, right   // Want a 10 pixel separation between the twoparts and the register panel   // above and the control panel below.   public Insets insets() {     return new Insets(0, 0, 0, 0);   } }