KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > tc > asm > attrs > StackMapAttribute


1 /**
2  * ASM: a very small and fast Java bytecode manipulation framework
3  * Copyright (c) 2000-2005 INRIA, France Telecom
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  * 3. Neither the name of the copyright holders nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28  * THE POSSIBILITY OF SUCH DAMAGE.
29  */

30 package com.tc.asm.attrs;
31
32 import java.util.ArrayList JavaDoc;
33 import java.util.HashSet JavaDoc;
34 import java.util.Iterator JavaDoc;
35 import java.util.List JavaDoc;
36 import java.util.Set JavaDoc;
37
38 import com.tc.asm.Attribute;
39 import com.tc.asm.ByteVector;
40 import com.tc.asm.ClassReader;
41 import com.tc.asm.ClassWriter;
42 import com.tc.asm.Label;
43
44 /**
45  * StackMapAttribute is used by CDLC preverifier. Definition is given in
46  * appendix "CLDC Byte Code Typechecker Specification" from CDLC 1.1
47  * specification. <p> <i>Note that this implementation does not calculate
48  * StackMapFrame structures from the method bytecode. If method code is changed
49  * or generated from scratch, then developer is responsible to prepare a correct
50  * StackMapFrame structures.</i> <p> The format of the stack map in the class
51  * file is given below. In the following, <ul> <li>if the length of the
52  * method's byte code1 is 65535 or less, then <tt>uoffset</tt> represents the
53  * type u2; otherwise <tt>uoffset</tt> represents the type u4.</li> <li>If
54  * the maximum number of local variables for the method is 65535 or less, then
55  * <tt>ulocalvar</tt> represents the type u2; otherwise <tt>ulocalvar</tt>
56  * represents the type u4.</li> <li>If the maximum size of the operand stack
57  * is 65535 or less, then <tt>ustack</tt> represents the type u2; otherwise
58  * ustack represents the type u4.</li> </ul>
59  *
60  * <pre>
61  * stack_map { // attribute StackMap
62  * u2 attribute_name_index;
63  * u4 attribute_length
64  * uoffset number_of_entries;
65  * stack_map_frame entries[number_of_entries];
66  * }
67  * </pre>
68  *
69  * Each stack map frame has the following format:
70  *
71  * <pre>
72  * stack_map_frame {
73  * uoffset offset;
74  * ulocalvar number_of_locals;
75  * verification_type_info locals[number_of_locals];
76  * ustack number_of_stack_items;
77  * verification_type_info stack[number_of_stack_items];
78  * }
79  * </pre>
80  *
81  * The <tt>verification_type_info</tt> structure consists of a one-byte tag
82  * followed by zero or more bytes, giving more information about the tag. Each
83  * <tt>verification_type_info</tt> structure specifies the verification type
84  * of one or two locations.
85  *
86  * <pre>
87  * union verification_type_info {
88  * Top_variable_info;
89  * Integer_variable_info;
90  * Float_variable_info;
91  * Long_variable_info;
92  * Double_variable_info;
93  * Null_variable_info;
94  * UninitializedThis_variable_info;
95  * Object_variable_info;
96  * Uninitialized_variable_info;
97  * }
98  *
99  * Top_variable_info {
100  * u1 tag = ITEM_Top; // 0
101  * }
102  *
103  * Integer_variable_info {
104  * u1 tag = ITEM_Integer; // 1
105  * }
106  *
107  * Float_variable_info {
108  * u1 tag = ITEM_Float; // 2
109  * }
110  *
111  * Long_variable_info {
112  * u1 tag = ITEM_Long; // 4
113  * }
114  *
115  * Double_variable_info {
116  * u1 tag = ITEM_Double; // 3
117  * }
118  *
119  * Null_variable_info {
120  * u1 tag = ITEM_Null; // 5
121  * }
122  *
123  * UninitializedThis_variable_info {
124  * u1 tag = ITEM_UninitializedThis; // 6
125  * }
126  *
127  * Object_variable_info {
128  * u1 tag = ITEM_Object; // 7
129  * u2 cpool_index;
130  * }
131  *
132  * Uninitialized_variable_info {
133  * u1 tag = ITEM_Uninitialized // 8
134  * uoffset offset;
135  * }
136  * </pre>
137  *
138  * @see <a HREF="http://www.jcp.org/en/jsr/detail?id=139">JSR 139 : Connected
139  * Limited Device Configuration 1.1</a>
140  *
141  * @author Eugene Kuleshov
142  */

143 public class StackMapAttribute extends Attribute {
144
145     static final int MAX_SIZE = 65535;
146
147     /**
148      * A List of <code>StackMapFrame</code> instances.
149      */

150     public List JavaDoc frames = new ArrayList JavaDoc();
151
152     public StackMapAttribute() {
153         super("StackMap");
154     }
155
156     public StackMapAttribute(List JavaDoc frames) {
157         this();
158         this.frames = frames;
159     }
160
161     public List JavaDoc getFrames() {
162         return frames;
163     }
164
165     public StackMapFrame getFrame(Label label) {
166         for (int i = 0; i < frames.size(); i++) {
167             StackMapFrame frame = (StackMapFrame) frames.get(i);
168             if (frame.label == label) {
169                 return frame;
170             }
171         }
172         return null;
173     }
174
175     public boolean isUnknown() {
176         return false;
177     }
178
179     public boolean isCodeAttribute() {
180         return true;
181     }
182
183     protected Attribute read(
184         ClassReader cr,
185         int off,
186         int len,
187         char[] buf,
188         int codeOff,
189         Label[] labels)
190     {
191         StackMapAttribute attr = new StackMapAttribute();
192         // note that this is not the size of Code attribute
193
boolean isExtCodeSize = cr.readInt(codeOff + 4) > MAX_SIZE;
194         boolean isExtLocals = cr.readUnsignedShort(codeOff + 2) > MAX_SIZE;
195         boolean isExtStack = cr.readUnsignedShort(codeOff) > MAX_SIZE;
196
197         int size = 0;
198         if (isExtCodeSize) {
199             size = cr.readInt(off);
200             off += 4;
201         } else {
202             size = cr.readUnsignedShort(off);
203             off += 2;
204         }
205         for (int i = 0; i < size; i++) {
206             int offset;
207             if (isExtCodeSize) {
208                 offset = cr.readInt(off);
209                 off += 4;
210             } else {
211                 offset = cr.readUnsignedShort(off);
212                 off += 2;
213             }
214
215             Label label = getLabel(offset, labels);
216             List JavaDoc locals = new ArrayList JavaDoc();
217             List JavaDoc stack = new ArrayList JavaDoc();
218
219             off = readTypeInfo(cr,
220                     off,
221                     locals,
222                     labels,
223                     buf,
224                     isExtLocals,
225                     isExtCodeSize);
226             off = readTypeInfo(cr,
227                     off,
228                     stack,
229                     labels,
230                     buf,
231                     isExtStack,
232                     isExtCodeSize);
233
234             attr.frames.add(new StackMapFrame(label, locals, stack));
235         }
236         return attr;
237     }
238
239     private int readTypeInfo(
240         ClassReader cr,
241         int off,
242         List JavaDoc info,
243         Label[] labels,
244         char[] buf,
245         boolean isExt,
246         boolean isExtCode)
247     {
248         int n = 0;
249         if (isExt) {
250             n = cr.readInt(off);
251             off += 4;
252         } else {
253             n = cr.readUnsignedShort(off);
254             off += 2;
255         }
256         for (int j = 0; j < n; j++) {
257             int itemType = cr.readByte(off++);
258             StackMapType typeInfo = StackMapType.getTypeInfo(itemType);
259             info.add(typeInfo);
260             switch (itemType) {
261                 case StackMapType.ITEM_Object: //
262
typeInfo.setObject(cr.readClass(off, buf));
263                     off += 2;
264                     break;
265                 case StackMapType.ITEM_Uninitialized: //
266
int offset;
267                     if (isExtCode) {
268                         offset = cr.readInt(off);
269                         off += 4;
270                     } else {
271                         offset = cr.readUnsignedShort(off);
272                         off += 2;
273                     }
274                     typeInfo.setLabel(getLabel(offset, labels));
275                     break;
276             }
277         }
278         return off;
279     }
280
281     private void writeTypeInfo(ByteVector bv, ClassWriter cw, List JavaDoc info, int max)
282     {
283         if (max > StackMapAttribute.MAX_SIZE) {
284             bv.putInt(info.size());
285         } else {
286             bv.putShort(info.size());
287         }
288         for (int j = 0; j < info.size(); j++) {
289             StackMapType typeInfo = (StackMapType) info.get(j);
290             bv.putByte(typeInfo.getType());
291             switch (typeInfo.getType()) {
292                 case StackMapType.ITEM_Object: //
293
bv.putShort(cw.newClass(typeInfo.getObject()));
294                     break;
295
296                 case StackMapType.ITEM_Uninitialized: //
297
bv.putShort(typeInfo.getLabel().getOffset());
298                     break;
299
300             }
301         }
302     }
303
304     private Label getLabel(int offset, Label[] labels) {
305         Label l = labels[offset];
306         if (l != null) {
307             return l;
308         }
309         return labels[offset] = new Label();
310     }
311
312     protected ByteVector write(
313         ClassWriter cw,
314         byte[] code,
315         int len,
316         int maxStack,
317         int maxLocals)
318     {
319         ByteVector bv = new ByteVector();
320         if (code != null && code.length > MAX_SIZE) { // TODO verify value
321
bv.putInt(frames.size());
322         } else {
323             bv.putShort(frames.size());
324         }
325         for (int i = 0; i < frames.size(); i++) {
326             writeFrame((StackMapFrame) frames.get(i),
327                     cw,
328                     maxStack,
329                     maxLocals,
330                     bv);
331         }
332         return bv;
333     }
334
335     protected Label[] getLabels() {
336         HashSet JavaDoc labels = new HashSet JavaDoc();
337         for (int i = 0; i < frames.size(); i++) {
338             getFrameLabels((StackMapFrame) frames.get(i), labels);
339         }
340         return (Label[]) labels.toArray(new Label[labels.size()]);
341     }
342
343     private void writeFrame(
344         StackMapFrame frame,
345         ClassWriter cw,
346         int maxStack,
347         int maxLocals,
348         ByteVector bv)
349     {
350         bv.putShort(frame.label.getOffset());
351         writeTypeInfo(bv, cw, frame.locals, maxLocals);
352         writeTypeInfo(bv, cw, frame.stack, maxStack);
353     }
354
355     private void getFrameLabels(StackMapFrame frame, Set JavaDoc labels) {
356         labels.add(frame.label);
357         getTypeInfoLabels(labels, frame.locals);
358         getTypeInfoLabels(labels, frame.stack);
359     }
360
361     private void getTypeInfoLabels(Set JavaDoc labels, List JavaDoc info) {
362         for (Iterator JavaDoc it = info.iterator(); it.hasNext();) {
363             StackMapType typeInfo = (StackMapType) it.next();
364             if (typeInfo.getType() == StackMapType.ITEM_Uninitialized) {
365                 labels.add(typeInfo.getLabel());
366             }
367         }
368     }
369
370     public String JavaDoc toString() {
371         StringBuffer JavaDoc sb = new StringBuffer JavaDoc("StackMap[");
372         for (int i = 0; i < frames.size(); i++) {
373             sb.append('\n').append('[').append(frames.get(i)).append(']');
374         }
375         sb.append("\n]");
376         return sb.toString();
377     }
378 }
379
Popular Tags