View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    * 
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software 
12   * distributed under the License is distributed on an "AS IS" BASIS, 
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
14   * See the License for the specific language governing permissions and 
15   * limitations under the License.
16   */
17  
18  
19  package org.apache.jdo.impl.enhancer.classfile;
20  
21  import java.io.PrintStream;
22  import java.util.Stack;
23  
24  /***
25   * An instruction which requires a integral constant as an immediate operand 
26   */
27  
28  public class InsnIntOp extends Insn {
29      /* The operand */
30      private int operandValue;
31  
32      /* public accessors */
33  
34      public int nStackArgs() {
35          return VMOp.ops[opcode()].nStackArgs();
36      }
37  
38      public int nStackResults() {
39          return VMOp.ops[opcode()].nStackResults();
40      }
41  
42      public String argTypes() {
43          return VMOp.ops[opcode()].argTypes();
44      }
45  
46      public String resultTypes() {
47          return VMOp.ops[opcode()].resultTypes();
48      }
49  
50      public boolean branches() {
51          return opcode() == opc_ret;
52      }
53  
54      public int value() {
55          return operandValue;
56      }
57  
58      /***
59       * Compares this instance with another for structural equality.
60       */
61      //@olsen: added method
62      public boolean isEqual(Stack msg, Object obj) {
63          if (!(obj instanceof InsnIntOp)) {
64              msg.push("obj/obj.getClass() = "
65                       + (obj == null ? null : obj.getClass()));
66              msg.push("this.getClass() = "
67                       + this.getClass());
68              return false;
69          }
70          InsnIntOp other = (InsnIntOp)obj;
71  
72          if (!super.isEqual(msg, other)) {
73              return false;
74          }
75  
76          if (this.operandValue != other.operandValue) {
77              msg.push(String.valueOf("operandValue = "
78                                      + other.operandValue));
79              msg.push(String.valueOf("operandValue = "
80                                      + this.operandValue));
81              return false;
82          }
83          return true;
84      }
85  
86      /* package local methods *//package-summary/html">class="comment"> package local methods *//package-summary.html">/* package local methods *//package-summary.html">class="comment"> package local methods */
87  
88      static String primType(int primIndex) {
89          switch (primIndex) {
90          case T_BOOLEAN:
91              return "boolean";
92          case T_CHAR:
93              return "char";
94          case T_FLOAT:
95              return "float";
96          case T_DOUBLE:
97              return "double";
98          case T_BYTE:
99              return "byte";
100         case T_SHORT:
101             return "short";
102         case T_INT:
103             return "int";
104         case T_LONG:
105             return "long";
106         default:
107             throw new InsnError ("Invalid primitive type(" + primIndex + ")");
108         }
109     }
110 
111     void print (PrintStream out, int indent) {
112         ClassPrint.spaces(out, indent);
113         if (opcode() == opc_newarray) 
114             out.println(offset() + "  opc_newarray  " + primType(operandValue));
115         else
116             out.println(offset() + "  " + opName(opcode()) + "  " + operandValue);
117     }
118 
119     int store(byte[] buf, int index) {
120         if (size() == 4) {
121             /* prefix with an opc_wide */
122             buf[index++] = (byte) opc_wide;
123         }
124 
125         buf[index++] = (byte) opcode();
126         if (size() > 2)
127             buf[index++] = (byte)(operandValue >> 8);
128         buf[index++] = (byte)(operandValue & 0xff);
129         return index;
130     }
131 
132 
133     /* return the size of the instruction in bytes */
134 
135     int size() {
136         switch(opcode()) {
137         case opc_bipush:
138         case opc_newarray:
139             /* These are always 1 byte constants */
140             return 2;
141 
142         case opc_sipush: /* a short constant */
143             /* This is always a 2 byte constant */
144             return 3;
145 
146         case opc_iload:
147         case opc_lload:
148         case opc_fload:
149         case opc_dload:
150         case opc_aload:
151         case opc_istore:
152         case opc_lstore:
153         case opc_fstore:
154         case opc_dstore:
155         case opc_astore:
156         case opc_ret:
157             /* These can be one or two byte constants specifying a local var.
158              * If a two byte constant, the constant is prefixed by a wide
159              * instruction */
160             if (operandValue < 256)
161                 return 2;
162             else
163                 return 4;
164 
165         default:
166             throw new InsnError ("invalid instruction " + opName(opcode()) +
167                                  " with an integer operand");
168         }
169     }
170 
171 
172     InsnIntOp (int theOpcode, int theOperand, int pc) {
173         super(theOpcode, pc);
174 
175         operandValue = theOperand;
176     }
177 
178 
179     InsnIntOp (int theOpcode, int theOperand) {
180         super(theOpcode, NO_OFFSET);
181 
182         operandValue = theOperand;
183         switch(theOpcode) {
184         case opc_bipush:
185         case opc_newarray:
186             /* These are always 1 byte constants */
187 
188         case opc_sipush: /* a short constant */
189             /* This is always a 2 byte constant */
190 
191         case opc_dload:
192         case opc_lload:
193         case opc_iload:
194         case opc_fload:
195         case opc_aload:
196         case opc_istore:
197         case opc_lstore:
198         case opc_fstore:
199         case opc_dstore:
200         case opc_astore:
201         case opc_ret:
202             /* These can be one or two byte constants specifying a local var */
203             break;
204 
205         default:
206             throw new InsnError ("attempt to create an " + opName(theOpcode) +
207                                  " with an integer operand");
208         }
209     }
210 }