Source Code Cross Referenced for StackMapTableAttribute.java in  » Profiler » JIP » org » objectweb » asm » jip » attrs » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Profiler » JIP » org.objectweb.asm.jip.attrs 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /**
002:         * ASM: a very small and fast Java bytecode manipulation framework
003:         * Copyright (c) 2000-2005 INRIA, France Telecom
004:         * All rights reserved.
005:         *
006:         * Redistribution and use in source and binary forms, with or without
007:         * modification, are permitted provided that the following conditions
008:         * are met:
009:         * 1. Redistributions of source code must retain the above copyright
010:         *    notice, this list of conditions and the following disclaimer.
011:         * 2. Redistributions in binary form must reproduce the above copyright
012:         *    notice, this list of conditions and the following disclaimer in the
013:         *    documentation and/or other materials provided with the distribution.
014:         * 3. Neither the name of the copyright holders nor the names of its
015:         *    contributors may be used to endorse or promote products derived from
016:         *    this software without specific prior written permission.
017:         *
018:         * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019:         * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
020:         * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
021:         * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
022:         * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
023:         * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
024:         * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
025:         * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
026:         * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
027:         * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
028:         * THE POSSIBILITY OF SUCH DAMAGE.
029:         */package org.objectweb.asm.jip.attrs;
030:
031:        import java.util.ArrayList;
032:        import java.util.Collections;
033:        import java.util.List;
034:
035:        import org.objectweb.asm.jip.Attribute;
036:        import org.objectweb.asm.jip.ByteVector;
037:        import org.objectweb.asm.jip.ClassReader;
038:        import org.objectweb.asm.jip.ClassWriter;
039:        import org.objectweb.asm.jip.Label;
040:        import org.objectweb.asm.jip.Opcodes;
041:        import org.objectweb.asm.jip.Type;
042:
043:        /**
044:         * The stack map attribute is used during the process of verification by
045:         * typechecking (§4.11.1). <br> <br> A stack map attribute consists of zero or
046:         * more stack map frames. Each stack map frame specifies (either explicitly or
047:         * implicitly) a bytecode offset, the verification types (§4.11.1) for the local
048:         * variables, and the verification types for the operand stack. <br> <br> The
049:         * type checker deals with and manipulates the expected types of a method's
050:         * local variables and operand stack. Throughout this section, a location refers
051:         * to either a single local variable or to a single operand stack entry. <br>
052:         * <br> We will use the terms stack frame map and type state interchangeably to
053:         * describe a mapping from locations in the operand stack and local variables of
054:         * a method to verification types. We will usually use the term stack frame map
055:         * when such a mapping is provided in the class file, and the term type state
056:         * when the mapping is inferred by the type checker. <br> <br> If a method's
057:         * Code attribute does not have a StackMapTable attribute, it has an implicit
058:         * stack map attribute. This implicit stack map attribute is equivalent to a
059:         * StackMapTable attribute with number_of_entries equal to zero. A method's Code
060:         * attribute may have at most one StackMapTable attribute, otherwise a
061:         * java.lang.ClassFormatError is thrown. <br> <br> The format of the stack map
062:         * in the class file is given below. In the following, if the length of the
063:         * method's byte code is 65535 or less, then uoffset represents the type u2;
064:         * otherwise uoffset represents the type u4. If the maximum number of local
065:         * variables for the method is 65535 or less, then <code>ulocalvar</code>
066:         * represents the type u2; otherwise ulocalvar represents the type u4. If the
067:         * maximum size of the operand stack is 65535 or less, then <code>ustack</code>
068:         * represents the type u2; otherwise ustack represents the type u4.
069:         * 
070:         * <pre>
071:         * stack_map { // attribute StackMapTable
072:         *   u2 attribute_name_index;
073:         *   u4 attribute_length
074:         *   uoffset number_of_entries;
075:         *   stack_map_frame entries[number_of_entries];
076:         * }
077:         * </pre>
078:         * 
079:         * Each stack_map_frame structure specifies the type state at a particular byte
080:         * code offset. Each frame type specifies (explicitly or implicitly) a value,
081:         * offset_delta, that is used to calulate the actual byte code offset at which
082:         * it applies. The byte code offset at which the frame applies is given by
083:         * adding <code>1 + offset_delta</code> to the <code>offset</code> of the
084:         * previous frame, unless the previous frame is the initial frame of the method,
085:         * in which case the byte code offset is <code>offset_delta</code>. <br> <br>
086:         * <i>Note that the length of the byte codes is not the same as the length of
087:         * the Code attribute. The byte codes are embedded in the Code attribute, along
088:         * with other information.</i> <br> <br> By using an offset delta rather than
089:         * the actual byte code offset we ensure, by definition, that stack map frames
090:         * are in the correctly sorted order. Furthermore, by consistently using the
091:         * formula <code>offset_delta + 1</code> for all explicit frames, we guarantee
092:         * the absence of duplicates. <br> <br> All frame types, even full_frame, rely
093:         * on the previous frame for some of their semantics. This raises the question
094:         * of what is the very first frame? The initial frame is implicit, and computed
095:         * from the method descriptor. See the Prolog code for methodInitialStacFrame.
096:         * <br> <br> The stack_map_frame structure consists of a one-byte tag followed
097:         * by zero or more bytes, giving more information, depending upon the tag. <br>
098:         * <br> A stack map frame may belong to one of several frame types
099:         * 
100:         * <pre>
101:         * union stack_map_frame {
102:         *   same_frame;
103:         *   same_locals_1_stack_item_frame;
104:         *   chop_frame;
105:         *   same_frame_extended;
106:         *   append_frame;
107:         *   full_frame;
108:         * }
109:         * </pre>
110:         * 
111:         * The frame type same_frame is represented by tags in the range [0-63]. If the
112:         * frame type is same_frame, it means the frame has exactly the same locals as
113:         * the previous stack map frame and that the number of stack items is zero. The
114:         * offset_delta value for the frame is the value of the tag field, frame_type.
115:         * The form of such a frame is then:
116:         * 
117:         * <pre>
118:         * same_frame {
119:         *   u1 frame_type = SAME;  // 0-63
120:         * }
121:         * </pre>
122:         * 
123:         * The frame type same_locals_1_stack_item_frame is represented by tags in the
124:         * range [64, 127]. If the frame_type is same_locals_1_stack_item_frame, it
125:         * means the frame has exactly the same locals as the previous stack map frame
126:         * and that the number of stack items is 1. The offset_delta value for the frame
127:         * is the value (frame_type - 64). There is a verification_type_info following
128:         * the frame_type for the one stack item. The form of such a frame is then:
129:         * 
130:         * <pre>
131:         * same_locals_1_stack_item_frame {
132:         *   u1 frame_type = SAME_LOCALS_1_STACK_ITEM;  // 64-127
133:         *    verification_type_info stack[1];
134:         * }
135:         * </pre>
136:         * 
137:         * Tags in the range [128-247] are reserved for future use. <br> <br> The frame
138:         * type chop_frame is represented by tags in the range [248-250]. If the
139:         * frame_type is chop_frame, it means that the current locals are the same as
140:         * the locals in the previous frame, except that the k last locals are absent.
141:         * The value of k is given by the formula 251-frame_type. <br> <br> The form of
142:         * such a frame is then:
143:         * 
144:         * <pre>
145:         * chop_frame {
146:         *   u1 frame_type=CHOP;  // 248-250
147:         *   uoffset offset_delta;
148:         * }
149:         * </pre>
150:         * 
151:         * The frame type same_frame_extended is represented by the tag value 251. If
152:         * the frame type is same_frame_extended, it means the frame has exactly the
153:         * same locals as the previous stack map frame and that the number of stack
154:         * items is zero. The form of such a frame is then:
155:         * 
156:         * <pre>
157:         * same_frame_extended {
158:         *   u1 frame_type = SAME_FRAME_EXTENDED;  // 251
159:         *   uoffset offset_delta;
160:         * }
161:         * </pre>
162:         * 
163:         * The frame type append_frame is represented by tags in the range [252-254]. If
164:         * the frame_type is append_frame, it means that the current locals are the same
165:         * as the locals in the previous frame, except that k additional locals are
166:         * defined. The value of k is given by the formula frame_type-251. <br> <br> The
167:         * form of such a frame is then:
168:         * 
169:         * <pre>
170:         * append_frame {
171:         *   u1 frame_type =APPEND;  // 252-254
172:         *   uoffset offset_delta;
173:         *   verification_type_info locals[frame_type -251];
174:         * }
175:         * </pre>
176:         * 
177:         * The 0th entry in locals represents the type of the first additional local
178:         * variable. If locals[M] represents local variable N, then locals[M+1]
179:         * represents local variable N+1 if locals[M] is one of Top_variable_info,
180:         * Integer_variable_info, Float_variable_info, Null_variable_info,
181:         * UninitializedThis_variable_info, Object_variable_info, or
182:         * Uninitialized_variable_info, otherwise locals[M+1] represents local variable
183:         * N+2. It is an error if, for any index i, locals[i] represents a local
184:         * variable whose index is greater than the maximum number of local variables
185:         * for the method. <br> <br> The frame type full_frame is represented by the tag
186:         * value 255. The form of such a frame is then:
187:         * 
188:         * <pre>
189:         * full_frame {
190:         *   u1 frame_type = FULL_FRAME;  // 255
191:         *   uoffset offset_delta;
192:         *   ulocalvar number_of_locals;
193:         *   verification_type_info locals[number_of_locals];
194:         *   ustack number_of_stack_items;
195:         *   verification_type_info stack[number_of_stack_items];
196:         * }
197:         * </pre>
198:         * 
199:         * The 0th entry in locals represents the type of local variable 0. If locals[M]
200:         * represents local variable N, then locals[M+1] represents local variable N+1
201:         * if locals[M] is one of Top_variable_info, Integer_variable_info,
202:         * Float_variable_info, Null_variable_info, UninitializedThis_variable_info,
203:         * Object_variable_info, or Uninitialized_variable_info, otherwise locals[M+1]
204:         * represents local variable N+2. It is an error if, for any index i, locals[i]
205:         * represents a local variable whose index is greater than the maximum number of
206:         * local variables for the method. <br> <br> The 0th entry in stack represents
207:         * the type of the bottom of the stack, and subsequent entries represent types
208:         * of stack elements closer to the top of the operand stack. We shall refer to
209:         * the bottom element of the stack as stack element 0, and to subsequent
210:         * elements as stack element 1, 2 etc. If stack[M] represents stack element N,
211:         * then stack[M+1] represents stack element N+1 if stack[M] is one of
212:         * Top_variable_info, Integer_variable_info, Float_variable_info,
213:         * Null_variable_info, UninitializedThis_variable_info, Object_variable_info, or
214:         * Uninitialized_variable_info, otherwise stack[M+1] represents stack element
215:         * N+2. It is an error if, for any index i, stack[i] represents a stack entry
216:         * whose index is greater than the maximum operand stack size for the method.
217:         * <br> <br> We say that an instruction in the byte code has a corresponding
218:         * stack map frame if the offset in the offset field of the stack map frame is
219:         * the same as the offset of the instruction in the byte codes. <br> <br> The
220:         * verification_type_info structure consists of a one-byte tag followed by zero
221:         * or more bytes, giving more information about the tag. Each
222:         * verification_type_info structure specifies the verification type of one or
223:         * two locations.
224:         * 
225:         * <pre>
226:         * union verification_type_info {
227:         *   Top_variable_info;
228:         *   Integer_variable_info;
229:         *   Float_variable_info;
230:         *   Long_variable_info;
231:         *   Double_variable_info;
232:         *   Null_variable_info;
233:         *   UninitializedThis_variable_info;
234:         *   Object_variable_info;
235:         *   Uninitialized_variable_info;
236:         * }
237:         * </pre>
238:         * 
239:         * The Top_variable_info type indicates that the local variable has the
240:         * verification type top (T.)
241:         * 
242:         * <pre>
243:         * Top_variable_info {
244:         *   u1 tag = ITEM_Top; // 0
245:         * }
246:         * </pre>
247:         * 
248:         * The Integer_variable_info type indicates that the location contains the
249:         * verification type int.
250:         * 
251:         * <pre>
252:         * Integer_variable_info {
253:         *   u1 tag = ITEM_Integer; // 1
254:         * }
255:         * </pre>
256:         * 
257:         * The Float_variable_info type indicates that the location contains the
258:         * verification type float.
259:         * 
260:         * <pre>
261:         * Float_variable_info {
262:         *   u1 tag = ITEM_Float; // 2
263:         * }
264:         * </pre>
265:         * 
266:         * The Long_variable_info type indicates that the location contains the
267:         * verification type long. If the location is a local variable, then:
268:         * 
269:         * <ul> <li>It must not be the local variable with the highest index.</li>
270:         * <li>The next higher numbered local variable contains the verification type
271:         * T.</li> </ul>
272:         * 
273:         * If the location is an operand stack entry, then:
274:         * 
275:         * <ul> <li>The current location must not be the topmost location of the
276:         * operand stack.</li> <li>the next location closer to the top of the operand
277:         * stack contains the verification type T.</li> </ul>
278:         * 
279:         * This structure gives the contents of two locations in the operand stack or in
280:         * the local variables.
281:         * 
282:         * <pre>
283:         * Long_variable_info {
284:         *   u1 tag = ITEM_Long; // 4
285:         * }
286:         * </pre>
287:         * 
288:         * The Double_variable_info type indicates that the location contains the
289:         * verification type double. If the location is a local variable, then:
290:         * 
291:         * <ul> <li>It must not be the local variable with the highest index.</li>
292:         * <li>The next higher numbered local variable contains the verification type
293:         * T. <li> </ul>
294:         * 
295:         * If the location is an operand stack entry, then:
296:         * 
297:         * <ul> <li>The current location must not be the topmost location of the
298:         * operand stack.</li> <li>the next location closer to the top of the operand
299:         * stack contains the verification type T.</li> </ul>
300:         * 
301:         * This structure gives the contents of two locations in in the operand stack or
302:         * in the local variables.
303:         * 
304:         * <pre>
305:         * Double_variable_info {
306:         *   u1 tag = ITEM_Double; // 3
307:         * }
308:         * </pre>
309:         * 
310:         * The Null_variable_info type indicates that location contains the verification
311:         * type null.
312:         * 
313:         * <pre>
314:         * Null_variable_info {
315:         *   u1 tag = ITEM_Null; // 5
316:         * }
317:         * </pre>
318:         * 
319:         * The UninitializedThis_variable_info type indicates that the location contains
320:         * the verification type uninitializedThis.
321:         * 
322:         * <pre>
323:         * UninitializedThis_variable_info {
324:         *   u1 tag = ITEM_UninitializedThis; // 6
325:         * }
326:         * </pre>
327:         * 
328:         * The Object_variable_info type indicates that the location contains an
329:         * instance of the class referenced by the constant pool entry.
330:         * 
331:         * <pre>
332:         * Object_variable_info {
333:         *   u1 tag = ITEM_Object; // 7
334:         *   u2 cpool_index;
335:         * }
336:         * </pre>
337:         * 
338:         * The Uninitialized_variable_info indicates that the location contains the
339:         * verification type uninitialized(offset). The offset item indicates the offset
340:         * of the new instruction that created the object being stored in the location.
341:         * 
342:         * <pre>
343:         * Uninitialized_variable_info {
344:         *   u1 tag = ITEM_Uninitialized // 8
345:         *   uoffset offset;
346:         * }
347:         * </pre>
348:         * 
349:         * @see "ClassFileFormat-Java6.fm Page 138 Friday, April 15, 2005 3:22 PM"
350:         * 
351:         * @author Eugene Kuleshov
352:         */
353:        public class StackMapTableAttribute extends Attribute {
354:            /**
355:             * Frame has exactly the same locals as the previous stack map frame and
356:             * number of stack items is zero.
357:             */
358:            public static final int SAME_FRAME = 0; // to 63 (0-3f)
359:
360:            /**
361:             * Frame has exactly the same locals as the previous stack map frame and
362:             * number of stack items is 1
363:             */
364:            public static final int SAME_LOCALS_1_STACK_ITEM_FRAME = 64; // to 127
365:
366:            // (40-7f)
367:
368:            /**
369:             * Reserved for future use
370:             */
371:            public static final int RESERVED = 128;
372:
373:            /**
374:             * Frame has exactly the same locals as the previous stack map frame and
375:             * number of stack items is 1. Offset is bigger then 63;
376:             */
377:            public static final int SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED = 247; // f7
378:
379:            /**
380:             * Frame where current locals are the same as the locals in the previous
381:             * frame, except that the k last locals are absent. The value of k is given
382:             * by the formula 251-frame_type.
383:             */
384:            public static final int CHOP_FRAME = 248; // to 250 (f8-fA)
385:
386:            /**
387:             * Frame has exactly the same locals as the previous stack map frame and
388:             * number of stack items is zero. Offset is bigger then 63;
389:             */
390:            public static final int SAME_FRAME_EXTENDED = 251; // fb
391:
392:            /**
393:             * Frame where current locals are the same as the locals in the previous
394:             * frame, except that k additional locals are defined. The value of k is
395:             * given by the formula frame_type-251.
396:             */
397:            public static final int APPEND_FRAME = 252; // to 254 // fc-fe
398:
399:            /**
400:             * Full frame
401:             */
402:            public static final int FULL_FRAME = 255; // ff
403:
404:            private static final int MAX_SHORT = 65535;
405:
406:            /**
407:             * A <code>List</code> of <code>StackMapFrame</code> instances.
408:             */
409:            private List frames;
410:
411:            public StackMapTableAttribute() {
412:                super ("StackMapTable");
413:            }
414:
415:            public StackMapTableAttribute(List frames) {
416:                this ();
417:                this .frames = frames;
418:            }
419:
420:            public List getFrames() {
421:                return frames;
422:            }
423:
424:            public StackMapFrame getFrame(Label label) {
425:                for (int i = 0; i < frames.size(); i++) {
426:                    StackMapFrame frame = (StackMapFrame) frames.get(i);
427:                    if (frame.label == label) {
428:                        return frame;
429:                    }
430:                }
431:                return null;
432:            }
433:
434:            public boolean isUnknown() {
435:                return false;
436:            }
437:
438:            public boolean isCodeAttribute() {
439:                return true;
440:            }
441:
442:            protected Attribute read(ClassReader cr, int off, int len,
443:                    char[] buf, int codeOff, Label[] labels) {
444:
445:                ArrayList frames = new ArrayList();
446:
447:                // note that this is not the size of Code attribute
448:                boolean isExtCodeSize = cr.readInt(codeOff + 4) > MAX_SHORT;
449:                boolean isExtLocals = cr.readUnsignedShort(codeOff + 2) > MAX_SHORT;
450:                boolean isExtStack = cr.readUnsignedShort(codeOff) > MAX_SHORT;
451:
452:                int offset = 0;
453:
454:                int methodOff = getMethodOff(cr, codeOff, buf);
455:                StackMapFrame frame = new StackMapFrame(
456:                        getLabel(offset, labels), calculateLocals(cr.readClass(
457:                                cr.header + 2, buf), // owner
458:                                cr.readUnsignedShort(methodOff), // method access
459:                                cr.readUTF8(methodOff + 2, buf), // method name
460:                                cr.readUTF8(methodOff + 4, buf)), // method desc
461:                        Collections.EMPTY_LIST);
462:                frames.add(frame);
463:
464:                // System.err.println( cr.readUTF8( methodOff + 2, buf));
465:                // System.err.println( offset +" delta:" + 0 +" : "+ frame);
466:
467:                int size;
468:                if (isExtCodeSize) {
469:                    size = cr.readInt(off);
470:                    off += 4;
471:                } else {
472:                    size = cr.readUnsignedShort(off);
473:                    off += 2;
474:                }
475:
476:                for (; size > 0; size--) {
477:                    int tag = cr.readByte(off); // & 0xff;
478:                    off++;
479:
480:                    List stack;
481:                    List locals;
482:
483:                    int offsetDelta;
484:                    if (tag < SAME_LOCALS_1_STACK_ITEM_FRAME) { // SAME_FRAME
485:                        offsetDelta = tag;
486:
487:                        locals = new ArrayList(frame.locals);
488:                        stack = Collections.EMPTY_LIST;
489:
490:                    } else if (tag < RESERVED) { // SAME_LOCALS_1_STACK_ITEM_FRAME
491:                        offsetDelta = tag - SAME_LOCALS_1_STACK_ITEM_FRAME;
492:
493:                        locals = new ArrayList(frame.locals);
494:                        stack = new ArrayList();
495:                        // read verification_type_info stack[1];
496:                        off = readType(stack, isExtCodeSize, cr, off, labels,
497:                                buf);
498:
499:                    } else {
500:                        if (isExtCodeSize) {
501:                            offsetDelta = cr.readInt(off);
502:                            off += 4;
503:                        } else {
504:                            offsetDelta = cr.readUnsignedShort(off);
505:                            off += 2;
506:                        }
507:
508:                        if (tag == SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) { // SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED
509:                            locals = new ArrayList(frame.locals);
510:                            stack = new ArrayList();
511:                            // read verification_type_info stack[1];
512:                            off = readType(stack, isExtCodeSize, cr, off,
513:                                    labels, buf);
514:
515:                        } else if (tag >= CHOP_FRAME
516:                                && tag < SAME_FRAME_EXTENDED) { // CHOP_FRAME
517:                            stack = Collections.EMPTY_LIST;
518:
519:                            int k = SAME_FRAME_EXTENDED - tag;
520:                            // copy locals from prev frame and chop last k
521:                            locals = new ArrayList(frame.locals.subList(0,
522:                                    frame.locals.size() - k));
523:
524:                        } else if (tag == SAME_FRAME_EXTENDED) { // SAME_FRAME_EXTENDED
525:                            stack = Collections.EMPTY_LIST;
526:                            locals = new ArrayList(frame.locals);
527:
528:                        } else if ( /* tag>=APPEND && */tag < FULL_FRAME) { // APPEND_FRAME
529:                            stack = Collections.EMPTY_LIST;
530:
531:                            // copy locals from prev frame and append new k
532:                            locals = new ArrayList(frame.locals);
533:                            for (int k = tag - SAME_FRAME_EXTENDED; k > 0; k--) {
534:                                off = readType(locals, isExtCodeSize, cr, off,
535:                                        labels, buf);
536:                            }
537:
538:                        } else if (tag == FULL_FRAME) { // FULL_FRAME
539:                            // read verification_type_info locals[number_of_locals];
540:                            locals = new ArrayList();
541:                            off = readTypes(locals, isExtLocals, isExtCodeSize,
542:                                    cr, off, labels, buf);
543:
544:                            // read verification_type_info stack[number_of_stack_items];
545:                            stack = new ArrayList();
546:                            off = readTypes(stack, isExtStack, isExtCodeSize,
547:                                    cr, off, labels, buf);
548:
549:                        } else {
550:                            throw new RuntimeException("Unknown frame type "
551:                                    + tag + " after offset " + offset);
552:
553:                        }
554:                    }
555:
556:                    offset += offsetDelta;
557:
558:                    Label offsetLabel = getLabel(offset, labels);
559:
560:                    frame = new StackMapFrame(offsetLabel, locals, stack);
561:                    frames.add(frame);
562:                    // System.err.println( tag +" " + offset +" delta:" + offsetDelta +
563:                    // " frameType:"+ frameType+" : "+ frame);
564:
565:                    offset++;
566:                }
567:
568:                return new StackMapTableAttribute(frames);
569:            }
570:
571:            protected ByteVector write(ClassWriter cw, byte[] code, int len,
572:                    int maxStack, int maxLocals) {
573:                ByteVector bv = new ByteVector();
574:                // TODO verify this value (MAX_SHORT)
575:                boolean isExtCodeSize = code != null && code.length > MAX_SHORT;
576:                writeSize(frames.size() - 1, bv, isExtCodeSize);
577:
578:                if (frames.size() < 2) {
579:                    return bv;
580:                }
581:
582:                boolean isExtLocals = maxLocals > MAX_SHORT;
583:                boolean isExtStack = maxStack > MAX_SHORT;
584:
585:                // skip the first frame
586:                StackMapFrame frame = (StackMapFrame) frames.get(0);
587:                List locals = frame.locals;
588:                int offset = frame.label.getOffset();
589:
590:                for (int i = 1; i < frames.size(); i++) {
591:                    frame = (StackMapFrame) frames.get(i);
592:
593:                    List clocals = frame.locals;
594:                    List cstack = frame.stack;
595:                    int coffset = frame.label.getOffset();
596:
597:                    int clocalsSize = clocals.size();
598:                    int cstackSize = cstack.size();
599:
600:                    int localsSize = locals.size();
601:
602:                    int delta = coffset - offset;
603:
604:                    int type = FULL_FRAME;
605:                    int k = 0;
606:                    if (cstackSize == 0) {
607:                        k = clocalsSize - localsSize;
608:                        switch (k) {
609:                        case -3:
610:                        case -2:
611:                        case -1:
612:                            type = CHOP_FRAME; // CHOP or FULL
613:                            localsSize = clocalsSize; // for full_frame check
614:                            break;
615:
616:                        case 0:
617:                            // SAME, SAME_EXTENDED or FULL
618:                            type = delta < 64 ? SAME_FRAME
619:                                    : SAME_FRAME_EXTENDED;
620:                            break;
621:
622:                        case 1:
623:                        case 2:
624:                        case 3:
625:                            type = APPEND_FRAME; // APPEND or FULL
626:                            break;
627:                        }
628:                    } else if (localsSize == clocalsSize && cstackSize == 1) {
629:                        // SAME_LOCAL_1_STACK or FULL
630:                        type = delta < 63 ? SAME_LOCALS_1_STACK_ITEM_FRAME
631:                                : SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED;
632:                    }
633:
634:                    if (type != FULL_FRAME) {
635:                        // verify if stack and locals are the same
636:                        for (int j = 0; j < localsSize && type != FULL_FRAME; j++) {
637:                            if (!locals.get(j).equals(clocals.get(j)))
638:                                type = FULL_FRAME;
639:                        }
640:                    }
641:
642:                    switch (type) {
643:                    case SAME_FRAME:
644:                        bv.putByte(delta);
645:                        break;
646:
647:                    case SAME_LOCALS_1_STACK_ITEM_FRAME:
648:                        bv.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME + delta);
649:                        writeTypeInfos(bv, cw, cstack, 0, 1);
650:                        break;
651:
652:                    case SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED:
653:                        bv.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED);
654:                        writeSize(delta, bv, isExtCodeSize);
655:                        writeTypeInfos(bv, cw, cstack, 0, 1);
656:                        break;
657:
658:                    case SAME_FRAME_EXTENDED:
659:                        bv.putByte(SAME_FRAME_EXTENDED);
660:                        writeSize(delta, bv, isExtCodeSize);
661:                        break;
662:
663:                    case CHOP_FRAME:
664:                        bv.putByte(SAME_FRAME_EXTENDED + k); // negative k
665:                        writeSize(delta, bv, isExtCodeSize);
666:                        break;
667:
668:                    case APPEND_FRAME:
669:                        bv.putByte(SAME_FRAME_EXTENDED + k); // positive k
670:                        writeSize(delta, bv, isExtCodeSize);
671:                        writeTypeInfos(bv, cw, clocals, clocalsSize - 1,
672:                                clocalsSize);
673:                        break;
674:
675:                    case FULL_FRAME:
676:                        bv.putByte(FULL_FRAME);
677:                        writeSize(delta, bv, isExtCodeSize);
678:                        writeSize(clocalsSize, bv, isExtLocals);
679:                        writeTypeInfos(bv, cw, clocals, 0, clocalsSize);
680:                        writeSize(cstackSize, bv, isExtStack);
681:                        writeTypeInfos(bv, cw, cstack, 0, cstackSize);
682:                        break;
683:
684:                    default:
685:                        throw new RuntimeException();
686:                    }
687:                    offset = coffset + 1; // compensating non first offset
688:                    locals = clocals;
689:                }
690:                return bv;
691:            }
692:
693:            private void writeSize(int delta, ByteVector bv, boolean isExt) {
694:                if (isExt) {
695:                    bv.putInt(delta);
696:                } else {
697:                    bv.putShort(delta);
698:                }
699:            }
700:
701:            private void writeTypeInfos(ByteVector bv, ClassWriter cw,
702:                    List info, int start, int end) {
703:                for (int j = start; j < end; j++) {
704:                    StackMapType typeInfo = (StackMapType) info.get(j);
705:                    bv.putByte(typeInfo.getType());
706:
707:                    switch (typeInfo.getType()) {
708:                    case StackMapType.ITEM_Object: //
709:                        bv.putShort(cw.newClass(typeInfo.getObject()));
710:                        break;
711:
712:                    case StackMapType.ITEM_Uninitialized: //
713:                        bv.putShort(typeInfo.getLabel().getOffset());
714:                        break;
715:
716:                    }
717:                }
718:            }
719:
720:            public static int getMethodOff(ClassReader cr, int codeOff,
721:                    char[] buf) {
722:                int off = cr.header + 6;
723:
724:                int interfacesCount = cr.readUnsignedShort(off);
725:                off += 2 + interfacesCount * 2;
726:
727:                int fieldsCount = cr.readUnsignedShort(off);
728:                off += 2;
729:                for (; fieldsCount > 0; --fieldsCount) {
730:                    int attrCount = cr.readUnsignedShort(off + 6); // field attributes
731:                    off += 8;
732:                    for (; attrCount > 0; --attrCount) {
733:                        off += 6 + cr.readInt(off + 2);
734:                    }
735:                }
736:
737:                int methodsCount = cr.readUnsignedShort(off);
738:                off += 2;
739:                for (; methodsCount > 0; --methodsCount) {
740:                    int methodOff = off;
741:                    int attrCount = cr.readUnsignedShort(off + 6); // method attributes
742:                    off += 8;
743:                    for (; attrCount > 0; --attrCount) {
744:                        String attrName = cr.readUTF8(off, buf);
745:                        off += 6;
746:                        if (attrName.equals("Code")) {
747:                            if (codeOff == off) {
748:                                return methodOff;
749:                            }
750:                        }
751:                        off += cr.readInt(off - 4);
752:                    }
753:                }
754:
755:                return -1;
756:            }
757:
758:            /**
759:             * Use method signature and access flags to resolve initial locals state.
760:             * 
761:             * @param className name of the method's owner class.
762:             * @param access access flags of the method.
763:             * @param methodName name of the method.
764:             * @param methodDesc descriptor of the method.
765:             * @return list of <code>StackMapType</code> instances representing locals
766:             *         for an initial frame.
767:             */
768:            public static List calculateLocals(String className, int access,
769:                    String methodName, String methodDesc) {
770:                List locals = new ArrayList();
771:
772:                // TODO
773:                if ("<init>".equals(methodName)
774:                        && !className.equals("java/lang/Object")) {
775:                    StackMapType typeInfo = StackMapType
776:                            .getTypeInfo(StackMapType.ITEM_UninitializedThis);
777:                    typeInfo.setObject(className); // this
778:                    locals.add(typeInfo);
779:                } else if ((access & Opcodes.ACC_STATIC) == 0) {
780:                    StackMapType typeInfo = StackMapType
781:                            .getTypeInfo(StackMapType.ITEM_Object);
782:                    typeInfo.setObject(className); // this
783:                    locals.add(typeInfo);
784:                }
785:
786:                Type[] types = Type.getArgumentTypes(methodDesc);
787:                for (int i = 0; i < types.length; i++) {
788:                    Type t = types[i];
789:                    StackMapType smt;
790:                    switch (t.getSort()) {
791:                    case Type.LONG:
792:                        smt = StackMapType.getTypeInfo(StackMapType.ITEM_Long);
793:                        break;
794:                    case Type.DOUBLE:
795:                        smt = StackMapType
796:                                .getTypeInfo(StackMapType.ITEM_Double);
797:                        break;
798:
799:                    case Type.FLOAT:
800:                        smt = StackMapType.getTypeInfo(StackMapType.ITEM_Float);
801:                        break;
802:
803:                    case Type.ARRAY:
804:                    case Type.OBJECT:
805:                        smt = StackMapType
806:                                .getTypeInfo(StackMapType.ITEM_Object);
807:                        smt.setObject(t.getDescriptor()); // TODO verify name
808:                        break;
809:
810:                    default:
811:                        smt = StackMapType
812:                                .getTypeInfo(StackMapType.ITEM_Integer);
813:                        break;
814:                    }
815:                }
816:
817:                return locals;
818:            }
819:
820:            private int readTypes(List info, boolean isExt,
821:                    boolean isExtCodeSize, ClassReader cr, int off,
822:                    Label[] labels, char[] buf) {
823:                int n = 0;
824:                if (isExt) {
825:                    n = cr.readInt(off);
826:                    off += 4;
827:                } else {
828:                    n = cr.readUnsignedShort(off);
829:                    off += 2;
830:                }
831:
832:                for (; n > 0; n--) {
833:                    off = readType(info, isExtCodeSize, cr, off, labels, buf);
834:                }
835:                return off;
836:            }
837:
838:            private int readType(List info, boolean isExtCodeSize,
839:                    ClassReader cr, int off, Label[] labels, char[] buf) {
840:                int itemType = cr.readByte(off++);
841:                StackMapType typeInfo = StackMapType.getTypeInfo(itemType);
842:                info.add(typeInfo);
843:                switch (itemType) {
844:                // case StackMapType.ITEM_Long: //
845:                // case StackMapType.ITEM_Double: //
846:                // info.add(StackMapType.getTypeInfo(StackMapType.ITEM_Top));
847:                // break;
848:
849:                case StackMapType.ITEM_Object: //
850:                    typeInfo.setObject(cr.readClass(off, buf));
851:                    off += 2;
852:                    break;
853:
854:                case StackMapType.ITEM_Uninitialized: //
855:                    int offset;
856:                    if (isExtCodeSize) {
857:                        offset = cr.readInt(off);
858:                        off += 4;
859:                    } else {
860:                        offset = cr.readUnsignedShort(off);
861:                        off += 2;
862:                    }
863:
864:                    typeInfo.setLabel(getLabel(offset, labels));
865:                    break;
866:                }
867:                return off;
868:            }
869:
870:            private Label getLabel(int offset, Label[] labels) {
871:                Label l = labels[offset];
872:                if (l != null) {
873:                    return l;
874:                }
875:                return labels[offset] = new Label();
876:            }
877:
878:            public String toString() {
879:                StringBuffer sb = new StringBuffer("StackMapTable[");
880:                for (int i = 0; i < frames.size(); i++) {
881:                    sb.append('\n').append('[').append(frames.get(i)).append(
882:                            ']');
883:                }
884:                sb.append("\n]");
885:                return sb.toString();
886:            }
887:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.