1 cananian 1.1.2.2 // AttributeCode.java, created Mon Jan 18 22:44:34 1999 by cananian
  2 cananian 1.1.2.1 // Copyright (C) 1998 C. Scott Ananian <cananian@alumni.princeton.edu>
  3 cananian 1.1.2.1 // Licensed under the terms of the GNU GPL; see COPYING for details.
  4 cananian 1.1.2.1 package harpoon.IR.RawClass;
  5 cananian 1.1.2.1 
  6 cananian 1.1.2.1 /**
  7 cananian 1.1.2.1  * The <code>Code</code> attribute is a variable-length attribute used
  8 cananian 1.1.2.1  * in the <code>attributes</code> table of <code>method_info</code>
  9 cananian 1.1.2.1  * structures.  A <code>Code</code> attribute contains the Java Virtual
 10 cananian 1.1.2.1  * Machine instructions and auxilliary information for a single Java
 11 cananian 1.1.2.1  * method, instance initialization method, or class or interface
 12 cananian 1.1.2.1  * initialization method.  There must be exactly one <code>Code</code>
 13 cananian 1.1.2.1  * attribute in each <code>method_info</code> structure.
 14 cananian 1.1.2.1  *
 15 cananian 1.1.2.1  * @author  C. Scott Ananian <cananian@alumni.princeton.edu>
 16 cananian 1.4      * @version $Id: AttributeCode.java,v 1.4 2003/09/05 22:09:59 cananian Exp $
 17 cananian 1.1.2.1  * @see "The Java Virtual Machine Specification, section 4.7.4"
 18 cananian 1.1.2.1  * @see AttributeLineNumberTable
 19 cananian 1.1.2.1  * @see AttributeLocalVariableTable
 20 cananian 1.1.2.1  * @see Attribute
 21 cananian 1.1.2.1  * @see MethodInfo
 22 cananian 1.1.2.1  * @see ClassFile
 23 cananian 1.1.2.1  */
 24 cananian 1.1.2.1 public class AttributeCode extends Attribute {
 25 cananian 1.3       /** The string naming this <code>Attribute</code> type. */
 26 cananian 1.3       public static final String ATTRIBUTE_NAME = "Code";
 27 cananian 1.1.2.1   /** The value of the <code>max_stack</code> item gives the maximum
 28 cananian 1.1.2.1       number of words on the operand stack at any point during
 29 cananian 1.1.2.1       execution of this method. */
 30 cananian 1.1.2.1   public int max_stack;
 31 cananian 1.1.2.1   /** The value of the <code>max_locals</code> item gives the number
 32 cananian 1.1.2.1       of local variables used by this method, including the parameters
 33 cananian 1.3           passed to the method on invocation.  The index of the first
 34 cananian 1.1.2.1       local variable is 0. */
 35 cananian 1.1.2.1   public int max_locals;
 36 cananian 1.1.2.1   /** The <code>code</code> array gives the actual bytes of Java
 37 cananian 1.1.2.1       Virtual Machine code that implement the method. */
 38 cananian 1.1.2.1   public byte code[];
 39 cananian 1.1.2.1   /** Each entry in the <code>exception_table</code> array describes
 40 cananian 1.1.2.1       one exception handler in the <code>code</code> array. */
 41 cananian 1.1.2.1   public ExceptionTable exception_table[];
 42 cananian 1.1.2.1   /** Each value of the <code>attributes</code> table must be a
 43 cananian 1.1.2.1       variable-length attribute structure.  A <code>Code</code>
 44 cananian 1.1.2.1       attribute can have any number of optional attributes associated
 45 cananian 1.4           with it.  <p> Currently, the <code>LineNumberTable</code> and
 46 cananian 1.1.2.1       <code>LocalVariableTable</code> attributes, both of which
 47 cananian 1.1.2.1       contain debugging information, are defined and used with the
 48 cananian 1.1.2.1       <code>Code</code> attribute. */
 49 cananian 1.1.2.1   public Attribute attributes[];
 50 cananian 1.1.2.1 
 51 cananian 1.1.2.1   /** Constructor. */
 52 cananian 1.1.2.1   AttributeCode(ClassFile parent, ClassDataInputStream in,
 53 cananian 1.1.2.1                 int attribute_name_index) throws java.io.IOException 
 54 cananian 1.1.2.1   {
 55 cananian 1.1.2.1     super(parent, attribute_name_index);
 56 cananian 1.1.2.1     long attribute_length = in.read_u4();
 57 cananian 1.1.2.1 
 58 cananian 1.1.2.1     max_stack = in.read_u2();
 59 cananian 1.1.2.1     max_locals= in.read_u2();
 60 cananian 1.1.2.1 
 61 cananian 1.1.2.1     long code_length = in.read_u4();
 62 cananian 1.1.2.1     code = new byte[(int)code_length]; // XXX ugly. dies after 31-bits
 63 cananian 1.1.2.1     for (long l=0; l<code_length; l++)
 64 cananian 1.1.2.1       code[(int)l] = in.readByte();    // XXX ugly. dies after 31-bits
 65 cananian 1.1.2.1 
 66 cananian 1.1.2.1     int exception_table_length = in.read_u2();
 67 cananian 1.1.2.1     exception_table = new ExceptionTable[exception_table_length];
 68 cananian 1.1.2.1     for (int i=0; i<exception_table_length; i++)
 69 cananian 1.1.2.1       exception_table[i] = new ExceptionTable(parent, in);
 70 cananian 1.1.2.1 
 71 cananian 1.1.2.1     int attributes_count = in.read_u2();
 72 cananian 1.1.2.1     attributes = new Attribute[attributes_count];
 73 cananian 1.1.2.1     for (int i=0; i<attributes_count; i++)
 74 cananian 1.1.2.1       attributes[i] = Attribute.read(parent, in);
 75 cananian 1.1.2.1 
 76 cananian 1.1.2.1     if (attribute_length != attribute_length())
 77 cananian 1.1.2.1       throw new ClassDataException("Code attribute of incorrect length" +
 78 cananian 1.1.2.1                             "("+attribute_length+"/"+attribute_length()+").");
 79 cananian 1.3         assert ATTRIBUTE_NAME.equals(attribute_name());
 80 cananian 1.1.2.1   }
 81 cananian 1.1.2.1 
 82 cananian 1.1.2.1   /** Constructor. */
 83 cananian 1.1.2.1   public AttributeCode(ClassFile parent, int attribute_name_index,
 84 cananian 1.1.2.1                        int max_stack, int max_locals, byte code[],
 85 cananian 1.1.2.1                        ExceptionTable exception_table[],
 86 cananian 1.1.2.1                        Attribute attributes[]) {
 87 cananian 1.1.2.1     super(parent, attribute_name_index);
 88 cananian 1.1.2.1     this.max_stack = max_stack;
 89 cananian 1.1.2.1     this.max_locals= max_locals;
 90 cananian 1.1.2.1     this.code = code;
 91 cananian 1.1.2.1     this.exception_table = exception_table;
 92 cananian 1.1.2.1     this.attributes = attributes;
 93 cananian 1.3         assert ATTRIBUTE_NAME.equals(attribute_name());
 94 cananian 1.1.2.1   }
 95 cananian 1.1.2.1   
 96 cananian 1.1.2.1   // convenience.
 97 cananian 1.1.2.1   public long code_length() { return code.length; }
 98 cananian 1.1.2.1   public int exception_table_length() { return exception_table.length; }
 99 cananian 1.1.2.1   public int attributes_count() { return attributes.length; }
100 cananian 1.1.2.1 
101 cananian 1.1.2.1   public long attribute_length() {
102 cananian 1.1.2.1     long len = 12 + code_length() + 8*exception_table_length();
103 cananian 1.1.2.1     for (int i=0; i < attributes.length; i++)
104 cananian 1.1.2.1       len += (6 + attributes[i].attribute_length() );
105 cananian 1.1.2.1     return len;
106 cananian 1.1.2.1   }
107 cananian 1.1.2.1 
108 cananian 1.1.2.1   /** Write to bytecode stream. */
109 cananian 1.1.2.1   public void write(ClassDataOutputStream out) throws java.io.IOException {
110 cananian 1.1.2.1     out.write_u2(attribute_name_index);
111 cananian 1.1.2.1     out.write_u4(attribute_length());
112 cananian 1.1.2.1 
113 cananian 1.1.2.1     out.write_u2(max_stack);
114 cananian 1.1.2.1     out.write_u2(max_locals);
115 cananian 1.1.2.1     
116 cananian 1.1.2.1     out.write_u4(code_length());
117 cananian 1.1.2.1     out.write(code);
118 cananian 1.1.2.1 
119 cananian 1.1.2.1     out.write_u2(exception_table_length());
120 cananian 1.1.2.1     for (int i=0; i<exception_table.length; i++)
121 cananian 1.1.2.1       exception_table[i].write(out);
122 cananian 1.1.2.1     
123 cananian 1.1.2.1     out.write_u2(attributes_count());
124 cananian 1.1.2.1     for (int i=0; i<attributes.length; i++)
125 cananian 1.1.2.1       attributes[i].write(out);
126 cananian 1.1.2.1   }
127 cananian 1.1.2.1 
128 cananian 1.1.2.1   /** 
129 cananian 1.4        * Return the symbolic name of a local variable, or <code>null</code> if
130 cananian 1.4        * one cannot be found.
131 cananian 1.1.2.1    * @param index the index of the local variable to look up.
132 cananian 1.4        * @return the name of the local, or <code>null</code>.
133 cananian 1.1.2.1    */
134 cananian 1.1.2.1   public String localName(int pc, int index) {
135 cananian 1.1.2.1     for(int i=0; i<attributes.length; i++)
136 cananian 1.1.2.1       if (attributes[i] instanceof AttributeLocalVariableTable) {
137 cananian 1.1.2.1         AttributeLocalVariableTable alvt = 
138 cananian 1.1.2.1           (AttributeLocalVariableTable) attributes[i];
139 cananian 1.1.2.1         String name = alvt.localName(pc, index);
140 cananian 1.1.2.1         if (name!=null) return name;
141 cananian 1.1.2.1       }
142 cananian 1.1.2.1     // Can't find a name for this in any table.
143 cananian 1.1.2.1     return null;
144 cananian 1.1.2.1   }
145 cananian 1.1.2.1 
146 cananian 1.1.2.1   /** Lookup a <code>Constant</code> in the <code>constant_pool</code>.
147 cananian 1.1.2.1    *  Provided for use of methods that parse the code array.
148 cananian 1.1.2.1    */
149 cananian 1.1.2.1   public Constant constant(int index) { return parent.constant_pool[index]; }
150 cananian 1.1.2.1 
151 cananian 1.1.2.1   /** Pretty-print the contents of this attribute.
152 cananian 1.1.2.1    *  @param indent the indentation level to use.
153 cananian 1.1.2.1    */
154 cananian 1.1.2.1   public void print(java.io.PrintWriter pw, int indent) {
155 cananian 1.1.2.1     int in = indent;
156 cananian 1.1.2.1     indent(pw, in, "Code Attribute:");
157 cananian 1.1.2.1     indent(pw, in+1, "Max Stack:   "+max_stack);
158 cananian 1.1.2.1     indent(pw, in+1, "Max Locals:  "+max_locals);
159 cananian 1.1.2.1     indent(pw, in+1, "Code length: "+code.length);
160 cananian 1.1.2.1     // skip the bytecode array.
161 cananian 1.1.2.1     indent(pw, in+1, "Exception Table ["+exception_table.length+"]:");
162 cananian 1.1.2.1     for (int i=0; i<exception_table.length; i++) {
163 cananian 1.1.2.1       indent(pw, in+2, "#"+i+": ");
164 cananian 1.1.2.1       exception_table[i].print(pw, in+3);
165 cananian 1.1.2.1     }
166 cananian 1.1.2.1     indent(pw, in+1, "Attributes ["+attributes.length+"]:");
167 cananian 1.1.2.1     for (int i=0; i<attributes.length; i++) {
168 cananian 1.1.2.1       indent(pw, in+2, "#"+i+": ");
169 cananian 1.1.2.1       attributes[i].print(pw, in+3);
170 cananian 1.1.2.1     }
171 cananian 1.1.2.1   }
172 cananian 1.2     }