001    /*
002     *  This file is part of the Jikes RVM project (http://jikesrvm.org).
003     *
004     *  This file is licensed to You under the Eclipse Public License (EPL);
005     *  You may not use this file except in compliance with the License. You
006     *  may obtain a copy of the License at
007     *
008     *      http://www.opensource.org/licenses/eclipse-1.0.php
009     *
010     *  See the COPYRIGHT.txt file distributed with this work for information
011     *  regarding copyright ownership.
012     */
013    package org.jikesrvm.compilers.opt.dfsolver;
014    
015    import java.util.Enumeration;
016    
017    import org.jikesrvm.compilers.opt.util.GraphNode;
018    
019    /**
020     * Represents a single Data Flow equation.
021     */
022    public class DF_Equation implements GraphNode {
023    
024      /**
025       * Evaluate this equation, setting a new value for the
026       * left-hand side.
027       *
028       * @return {@code true} if the lhs value changed. {@code false} otherwise
029       */
030      boolean evaluate() {
031        return operator.evaluate(operands);
032      }
033    
034      /**
035       * Return the left-hand side of this equation.
036       *
037       * @return the lattice cell this equation computes
038       */
039      DF_LatticeCell getLHS() {
040        return operands[0];
041      }
042    
043      /**
044       * Return the operands in this equation.
045       * @return the operands in this equation.
046       */
047      public DF_LatticeCell[] getOperands() {
048        return operands;
049      }
050    
051      /**
052       * Return the operator for this equation
053       * @return the operator for this equation
054       */
055      DF_Operator getOperator() {
056        return operator;
057      }
058    
059      /**
060       * Does this equation contain an appearance of a given cell?
061       * @param cell the cell in question
062       * @return true or false
063       */
064      public boolean hasCell(DF_LatticeCell cell) {
065        for (DF_LatticeCell operand : operands) {
066          if (operand == cell) {
067            return true;
068          }
069        }
070        return false;
071      }
072    
073      /**
074       * Return a string representation of this object
075       * @return a string representation of this object
076       */
077      @Override
078      public String toString() {
079        if (operands[0] == null) {
080          return ("NULL LHS");
081        }
082        String result = operands[0].toString();
083        result = result + " " + operator + " ";
084        for (int i = 1; i < operands.length; i++) {
085          result = result + operands[i] + "  ";
086        }
087        return result;
088      }
089    
090      /**
091       * Constructor for case of one operand on the right-hand side.
092       *
093       * @param lhs the lattice cell set by this equation
094       * @param operator the equation operator
095       * @param op1 the first operand on the rhs
096       */
097      DF_Equation(DF_LatticeCell lhs, DF_Operator operator, DF_LatticeCell op1) {
098        this.operator = operator;
099        operands = new DF_LatticeCell[2];
100        operands[0] = lhs;
101        operands[1] = op1;
102      }
103    
104      /**
105       * Constructor for case of two operands on the right-hand side.
106       *
107       * @param lhs the lattice cell set by this equation
108       * @param operator the equation operator
109       * @param op1 the first operand on the rhs
110       * @param op2 the second operand on the rhs
111       */
112      DF_Equation(DF_LatticeCell lhs, DF_Operator operator, DF_LatticeCell op1, DF_LatticeCell op2) {
113        this.operator = operator;
114        operands = new DF_LatticeCell[3];
115        operands[0] = lhs;
116        operands[1] = op1;
117        operands[2] = op2;
118      }
119    
120      /**
121       * Constructor for case of three operands on the right-hand side.
122       *
123       * @param lhs the lattice cell set by this equation
124       * @param operator the equation operator
125       * @param op1 the first operand on the rhs
126       * @param op2 the second operand on the rhs
127       * @param op3 the third operand on the rhs
128       */
129      DF_Equation(DF_LatticeCell lhs, DF_Operator operator, DF_LatticeCell op1, DF_LatticeCell op2,
130                      DF_LatticeCell op3) {
131        this.operator = operator;
132        operands = new DF_LatticeCell[4];
133        operands[0] = lhs;
134        operands[1] = op1;
135        operands[2] = op2;
136        operands[3] = op3;
137      }
138    
139      /**
140       * Constructor for case of more than three operands on the right-hand side.
141       *
142       * @param lhs the lattice cell set by this equation
143       * @param operator the equation operator
144       * @param rhs the operands of the right-hand side in order
145       */
146      DF_Equation(DF_LatticeCell lhs, DF_Operator operator, DF_LatticeCell[] rhs) {
147        this.operator = operator;
148        operands = new DF_LatticeCell[rhs.length + 1];
149        operands[0] = lhs;
150        for (int i = 0; i < rhs.length; i++) {
151          operands[i + 1] = rhs[i];
152        }
153      }
154    
155      /**
156       * Get the topological number for this equation
157       * @return the topological number
158       */
159      int getTopologicalNumber() {
160        return topologicalNumber;
161      }
162    
163      /**
164       * Get the topological number for this equation
165       * @param n the topological order
166       */
167      void setTopologicalNumber(int n) {
168        topologicalNumber = n;
169      }
170    
171      /* Implementation */
172      /**
173       * The operator in the equation
174       */
175      protected final DF_Operator operator;
176      /**
177       * The operands. Operand[0] is the left hand side.
178       */
179      protected final DF_LatticeCell[] operands;
180      /**
181       * The number of this equation when the system is sorted in topological
182       * order.
183       */
184      int topologicalNumber;
185      /**
186       * Field used for GraphNode interface.  TODO: is this needed?
187       */
188      private int index;
189    
190      /**
191       * Implementation of GraphNode interface.
192       */
193      @Override
194      public void setIndex(int i) {
195        index = i;
196      }
197    
198      @Override
199      public int getIndex() {
200        return index;
201      }
202    
203      /**
204       * Return an enumeration of the equations which use the result of this
205       * equation.
206       * @return an enumeration of the equations which use the result of this
207       * equation.
208       */
209      @Override
210      public Enumeration<GraphNode> outNodes() {
211        return new Enumeration<GraphNode>() {
212          private GraphNode elt = getLHS();
213    
214          @Override
215          public boolean hasMoreElements() {
216            return elt != null;
217          }
218    
219          @Override
220          public GraphNode nextElement() {
221            GraphNode x = elt;
222            elt = null;
223            return x;
224          }
225        };
226      }
227    
228      /**
229       * Return an enumeration of the equations upon whose results this
230       * equation depends.
231       * @return an enumeration of the equations upon whose results this
232       * equation depends
233       */
234      @Override
235      public Enumeration<GraphNode> inNodes() {
236        return new Enumeration<GraphNode>() {
237          private int i = 1;
238    
239          @Override
240          public boolean hasMoreElements() {
241            return (i < operands.length);
242          }
243    
244          @Override
245          public GraphNode nextElement() {
246            return operands[i++];
247          }
248        };
249      }
250    
251      private int scratch;
252    
253      @Override
254      public int getScratch() {
255        return scratch;
256      }
257    
258      @Override
259      public int setScratch(int o) {
260        return (scratch = o);
261      }
262    }