OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [tools/] [external/] [asm/] [org/] [objectweb/] [asm/] [attrs/] [StackMapTableAttribute.java] - Blame information for rev 779

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 779 jeremybenn
/**
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 org.objectweb.asm.attrs;
31
 
32
import java.util.ArrayList;
33
import java.util.Collections;
34
import java.util.List;
35
 
36
import org.objectweb.asm.Attribute;
37
import org.objectweb.asm.ByteVector;
38
import org.objectweb.asm.ClassReader;
39
import org.objectweb.asm.ClassWriter;
40
import org.objectweb.asm.Label;
41
import org.objectweb.asm.Opcodes;
42
import org.objectweb.asm.Type;
43
 
44
/**
45
 * The stack map attribute is used during the process of verification by
46
 * typechecking (§4.11.1). <br> <br> A stack map attribute consists of zero or
47
 * more stack map frames. Each stack map frame specifies (either explicitly or
48
 * implicitly) a bytecode offset, the verification types (§4.11.1) for the local
49
 * variables, and the verification types for the operand stack. <br> <br> The
50
 * type checker deals with and manipulates the expected types of a method's
51
 * local variables and operand stack. Throughout this section, a location refers
52
 * to either a single local variable or to a single operand stack entry. <br>
53
 * <br> We will use the terms stack frame map and type state interchangeably to
54
 * describe a mapping from locations in the operand stack and local variables of
55
 * a method to verification types. We will usually use the term stack frame map
56
 * when such a mapping is provided in the class file, and the term type state
57
 * when the mapping is inferred by the type checker. <br> <br> If a method's
58
 * Code attribute does not have a StackMapTable attribute, it has an implicit
59
 * stack map attribute. This implicit stack map attribute is equivalent to a
60
 * StackMapTable attribute with number_of_entries equal to zero. A method's Code
61
 * attribute may have at most one StackMapTable attribute, otherwise a
62
 * java.lang.ClassFormatError is thrown. <br> <br> The format of the stack map
63
 * in the class file is given below. In the following, if the length of the
64
 * method's byte code is 65535 or less, then uoffset represents the type u2;
65
 * otherwise uoffset represents the type u4. If the maximum number of local
66
 * variables for the method is 65535 or less, then <code>ulocalvar</code>
67
 * represents the type u2; otherwise ulocalvar represents the type u4. If the
68
 * maximum size of the operand stack is 65535 or less, then <code>ustack</code>
69
 * represents the type u2; otherwise ustack represents the type u4.
70
 *
71
 * <pre>
72
 * stack_map { // attribute StackMapTable
73
 *   u2 attribute_name_index;
74
 *   u4 attribute_length
75
 *   uoffset number_of_entries;
76
 *   stack_map_frame entries[number_of_entries];
77
 * }
78
 * </pre>
79
 *
80
 * Each stack_map_frame structure specifies the type state at a particular byte
81
 * code offset. Each frame type specifies (explicitly or implicitly) a value,
82
 * offset_delta, that is used to calulate the actual byte code offset at which
83
 * it applies. The byte code offset at which the frame applies is given by
84
 * adding <code>1 + offset_delta</code> to the <code>offset</code> of the
85
 * previous frame, unless the previous frame is the initial frame of the method,
86
 * in which case the byte code offset is <code>offset_delta</code>. <br> <br>
87
 * <i>Note that the length of the byte codes is not the same as the length of
88
 * the Code attribute. The byte codes are embedded in the Code attribute, along
89
 * with other information.</i> <br> <br> By using an offset delta rather than
90
 * the actual byte code offset we ensure, by definition, that stack map frames
91
 * are in the correctly sorted order. Furthermore, by consistently using the
92
 * formula <code>offset_delta + 1</code> for all explicit frames, we guarantee
93
 * the absence of duplicates. <br> <br> All frame types, even full_frame, rely
94
 * on the previous frame for some of their semantics. This raises the question
95
 * of what is the very first frame? The initial frame is implicit, and computed
96
 * from the method descriptor. See the Prolog code for methodInitialStacFrame.
97
 * <br> <br> The stack_map_frame structure consists of a one-byte tag followed
98
 * by zero or more bytes, giving more information, depending upon the tag. <br>
99
 * <br> A stack map frame may belong to one of several frame types
100
 *
101
 * <pre>
102
 * union stack_map_frame {
103
 *   same_frame;
104
 *   same_locals_1_stack_item_frame;
105
 *   chop_frame;
106
 *   same_frame_extended;
107
 *   append_frame;
108
 *   full_frame;
109
 * }
110
 * </pre>
111
 *
112
 * The frame type same_frame is represented by tags in the range [0-63]. If the
113
 * frame type is same_frame, it means the frame has exactly the same locals as
114
 * the previous stack map frame and that the number of stack items is zero. The
115
 * offset_delta value for the frame is the value of the tag field, frame_type.
116
 * The form of such a frame is then:
117
 *
118
 * <pre>
119
 * same_frame {
120
 *   u1 frame_type = SAME;  // 0-63
121
 * }
122
 * </pre>
123
 *
124
 * The frame type same_locals_1_stack_item_frame is represented by tags in the
125
 * range [64, 127]. If the frame_type is same_locals_1_stack_item_frame, it
126
 * means the frame has exactly the same locals as the previous stack map frame
127
 * and that the number of stack items is 1. The offset_delta value for the frame
128
 * is the value (frame_type - 64). There is a verification_type_info following
129
 * the frame_type for the one stack item. The form of such a frame is then:
130
 *
131
 * <pre>
132
 * same_locals_1_stack_item_frame {
133
 *   u1 frame_type = SAME_LOCALS_1_STACK_ITEM;  // 64-127
134
 *    verification_type_info stack[1];
135
 * }
136
 * </pre>
137
 *
138
 * Tags in the range [128-247] are reserved for future use. <br> <br> The frame
139
 * type chop_frame is represented by tags in the range [248-250]. If the
140
 * frame_type is chop_frame, it means that the current locals are the same as
141
 * the locals in the previous frame, except that the k last locals are absent.
142
 * The value of k is given by the formula 251-frame_type. <br> <br> The form of
143
 * such a frame is then:
144
 *
145
 * <pre>
146
 * chop_frame {
147
 *   u1 frame_type=CHOP;  // 248-250
148
 *   uoffset offset_delta;
149
 * }
150
 * </pre>
151
 *
152
 * The frame type same_frame_extended is represented by the tag value 251. If
153
 * the frame type is same_frame_extended, it means the frame has exactly the
154
 * same locals as the previous stack map frame and that the number of stack
155
 * items is zero. The form of such a frame is then:
156
 *
157
 * <pre>
158
 * same_frame_extended {
159
 *   u1 frame_type = SAME_FRAME_EXTENDED;  // 251
160
 *   uoffset offset_delta;
161
 * }
162
 * </pre>
163
 *
164
 * The frame type append_frame is represented by tags in the range [252-254]. If
165
 * the frame_type is append_frame, it means that the current locals are the same
166
 * as the locals in the previous frame, except that k additional locals are
167
 * defined. The value of k is given by the formula frame_type-251. <br> <br> The
168
 * form of such a frame is then:
169
 *
170
 * <pre>
171
 * append_frame {
172
 *   u1 frame_type =APPEND;  // 252-254
173
 *   uoffset offset_delta;
174
 *   verification_type_info locals[frame_type -251];
175
 * }
176
 * </pre>
177
 *
178
 * The 0th entry in locals represents the type of the first additional local
179
 * variable. If locals[M] represents local variable N, then locals[M+1]
180
 * represents local variable N+1 if locals[M] is one of Top_variable_info,
181
 * Integer_variable_info, Float_variable_info, Null_variable_info,
182
 * UninitializedThis_variable_info, Object_variable_info, or
183
 * Uninitialized_variable_info, otherwise locals[M+1] represents local variable
184
 * N+2. It is an error if, for any index i, locals[i] represents a local
185
 * variable whose index is greater than the maximum number of local variables
186
 * for the method. <br> <br> The frame type full_frame is represented by the tag
187
 * value 255. The form of such a frame is then:
188
 *
189
 * <pre>
190
 * full_frame {
191
 *   u1 frame_type = FULL_FRAME;  // 255
192
 *   uoffset offset_delta;
193
 *   ulocalvar number_of_locals;
194
 *   verification_type_info locals[number_of_locals];
195
 *   ustack number_of_stack_items;
196
 *   verification_type_info stack[number_of_stack_items];
197
 * }
198
 * </pre>
199
 *
200
 * The 0th entry in locals represents the type of local variable 0. If locals[M]
201
 * represents local variable N, then locals[M+1] represents local variable N+1
202
 * if locals[M] is one of Top_variable_info, Integer_variable_info,
203
 * Float_variable_info, Null_variable_info, UninitializedThis_variable_info,
204
 * Object_variable_info, or Uninitialized_variable_info, otherwise locals[M+1]
205
 * represents local variable N+2. It is an error if, for any index i, locals[i]
206
 * represents a local variable whose index is greater than the maximum number of
207
 * local variables for the method. <br> <br> The 0th entry in stack represents
208
 * the type of the bottom of the stack, and subsequent entries represent types
209
 * of stack elements closer to the top of the operand stack. We shall refer to
210
 * the bottom element of the stack as stack element 0, and to subsequent
211
 * elements as stack element 1, 2 etc. If stack[M] represents stack element N,
212
 * then stack[M+1] represents stack element N+1 if stack[M] is one of
213
 * Top_variable_info, Integer_variable_info, Float_variable_info,
214
 * Null_variable_info, UninitializedThis_variable_info, Object_variable_info, or
215
 * Uninitialized_variable_info, otherwise stack[M+1] represents stack element
216
 * N+2. It is an error if, for any index i, stack[i] represents a stack entry
217
 * whose index is greater than the maximum operand stack size for the method.
218
 * <br> <br> We say that an instruction in the byte code has a corresponding
219
 * stack map frame if the offset in the offset field of the stack map frame is
220
 * the same as the offset of the instruction in the byte codes. <br> <br> The
221
 * verification_type_info structure consists of a one-byte tag followed by zero
222
 * or more bytes, giving more information about the tag. Each
223
 * verification_type_info structure specifies the verification type of one or
224
 * two locations.
225
 *
226
 * <pre>
227
 * union verification_type_info {
228
 *   Top_variable_info;
229
 *   Integer_variable_info;
230
 *   Float_variable_info;
231
 *   Long_variable_info;
232
 *   Double_variable_info;
233
 *   Null_variable_info;
234
 *   UninitializedThis_variable_info;
235
 *   Object_variable_info;
236
 *   Uninitialized_variable_info;
237
 * }
238
 * </pre>
239
 *
240
 * The Top_variable_info type indicates that the local variable has the
241
 * verification type top (T.)
242
 *
243
 * <pre>
244
 * Top_variable_info {
245
 *   u1 tag = ITEM_Top; // 0
246
 * }
247
 * </pre>
248
 *
249
 * The Integer_variable_info type indicates that the location contains the
250
 * verification type int.
251
 *
252
 * <pre>
253
 * Integer_variable_info {
254
 *   u1 tag = ITEM_Integer; // 1
255
 * }
256
 * </pre>
257
 *
258
 * The Float_variable_info type indicates that the location contains the
259
 * verification type float.
260
 *
261
 * <pre>
262
 * Float_variable_info {
263
 *   u1 tag = ITEM_Float; // 2
264
 * }
265
 * </pre>
266
 *
267
 * The Long_variable_info type indicates that the location contains the
268
 * verification type long. If the location is a local variable, then:
269
 *
270
 * <ul> <li>It must not be the local variable with the highest index.</li>
271
 * <li>The next higher numbered local variable contains the verification type
272
 * T.</li> </ul>
273
 *
274
 * If the location is an operand stack entry, then:
275
 *
276
 * <ul> <li>The current location must not be the topmost location of the
277
 * operand stack.</li> <li>the next location closer to the top of the operand
278
 * stack contains the verification type T.</li> </ul>
279
 *
280
 * This structure gives the contents of two locations in the operand stack or in
281
 * the local variables.
282
 *
283
 * <pre>
284
 * Long_variable_info {
285
 *   u1 tag = ITEM_Long; // 4
286
 * }
287
 * </pre>
288
 *
289
 * The Double_variable_info type indicates that the location contains the
290
 * verification type double. If the location is a local variable, then:
291
 *
292
 * <ul> <li>It must not be the local variable with the highest index.</li>
293
 * <li>The next higher numbered local variable contains the verification type
294
 * T. <li> </ul>
295
 *
296
 * If the location is an operand stack entry, then:
297
 *
298
 * <ul> <li>The current location must not be the topmost location of the
299
 * operand stack.</li> <li>the next location closer to the top of the operand
300
 * stack contains the verification type T.</li> </ul>
301
 *
302
 * This structure gives the contents of two locations in in the operand stack or
303
 * in the local variables.
304
 *
305
 * <pre>
306
 * Double_variable_info {
307
 *   u1 tag = ITEM_Double; // 3
308
 * }
309
 * </pre>
310
 *
311
 * The Null_variable_info type indicates that location contains the verification
312
 * type null.
313
 *
314
 * <pre>
315
 * Null_variable_info {
316
 *   u1 tag = ITEM_Null; // 5
317
 * }
318
 * </pre>
319
 *
320
 * The UninitializedThis_variable_info type indicates that the location contains
321
 * the verification type uninitializedThis.
322
 *
323
 * <pre>
324
 * UninitializedThis_variable_info {
325
 *   u1 tag = ITEM_UninitializedThis; // 6
326
 * }
327
 * </pre>
328
 *
329
 * The Object_variable_info type indicates that the location contains an
330
 * instance of the class referenced by the constant pool entry.
331
 *
332
 * <pre>
333
 * Object_variable_info {
334
 *   u1 tag = ITEM_Object; // 7
335
 *   u2 cpool_index;
336
 * }
337
 * </pre>
338
 *
339
 * The Uninitialized_variable_info indicates that the location contains the
340
 * verification type uninitialized(offset). The offset item indicates the offset
341
 * of the new instruction that created the object being stored in the location.
342
 *
343
 * <pre>
344
 * Uninitialized_variable_info {
345
 *   u1 tag = ITEM_Uninitialized // 8
346
 *   uoffset offset;
347
 * }
348
 * </pre>
349
 *
350
 * @see "ClassFileFormat-Java6.fm Page 138 Friday, April 15, 2005 3:22 PM"
351
 *
352
 * @author Eugene Kuleshov
353
 */
354
public class StackMapTableAttribute extends Attribute {
355
    /**
356
     * Frame has exactly the same locals as the previous stack map frame and
357
     * number of stack items is zero.
358
     */
359
    public static final int SAME_FRAME = 0; // to 63 (0-3f)
360
 
361
    /**
362
     * Frame has exactly the same locals as the previous stack map frame and
363
     * number of stack items is 1
364
     */
365
    public static final int SAME_LOCALS_1_STACK_ITEM_FRAME = 64; // to 127
366
 
367
    // (40-7f)
368
 
369
    /**
370
     * Reserved for future use
371
     */
372
    public static final int RESERVED = 128;
373
 
374
    /**
375
     * Frame has exactly the same locals as the previous stack map frame and
376
     * number of stack items is 1. Offset is bigger then 63;
377
     */
378
    public static final int SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED = 247; // f7
379
 
380
    /**
381
     * Frame where current locals are the same as the locals in the previous
382
     * frame, except that the k last locals are absent. The value of k is given
383
     * by the formula 251-frame_type.
384
     */
385
    public static final int CHOP_FRAME = 248; // to 250 (f8-fA)
386
 
387
    /**
388
     * Frame has exactly the same locals as the previous stack map frame and
389
     * number of stack items is zero. Offset is bigger then 63;
390
     */
391
    public static final int SAME_FRAME_EXTENDED = 251; // fb
392
 
393
    /**
394
     * Frame where current locals are the same as the locals in the previous
395
     * frame, except that k additional locals are defined. The value of k is
396
     * given by the formula frame_type-251.
397
     */
398
    public static final int APPEND_FRAME = 252; // to 254 // fc-fe
399
 
400
    /**
401
     * Full frame
402
     */
403
    public static final int FULL_FRAME = 255; // ff
404
 
405
    private static final int MAX_SHORT = 65535;
406
 
407
    /**
408
     * A <code>List</code> of <code>StackMapFrame</code> instances.
409
     */
410
    private List frames;
411
 
412
    public StackMapTableAttribute() {
413
        super("StackMapTable");
414
    }
415
 
416
    public StackMapTableAttribute(List frames) {
417
        this();
418
        this.frames = frames;
419
    }
420
 
421
    public List getFrames() {
422
        return frames;
423
    }
424
 
425
    public StackMapFrame getFrame(Label label) {
426
        for (int i = 0; i < frames.size(); i++) {
427
            StackMapFrame frame = (StackMapFrame) frames.get(i);
428
            if (frame.label == label) {
429
                return frame;
430
            }
431
        }
432
        return null;
433
    }
434
 
435
    public boolean isUnknown() {
436
        return false;
437
    }
438
 
439
    public boolean isCodeAttribute() {
440
        return true;
441
    }
442
 
443
    protected Attribute read(
444
        ClassReader cr,
445
        int off,
446
        int len,
447
        char[] buf,
448
        int codeOff,
449
        Label[] labels)
450
    {
451
 
452
        ArrayList frames = new ArrayList();
453
 
454
        // note that this is not the size of Code attribute
455
        boolean isExtCodeSize = cr.readInt(codeOff + 4) > MAX_SHORT;
456
        boolean isExtLocals = cr.readUnsignedShort(codeOff + 2) > MAX_SHORT;
457
        boolean isExtStack = cr.readUnsignedShort(codeOff) > MAX_SHORT;
458
 
459
        int offset = 0;
460
 
461
        int methodOff = getMethodOff(cr, codeOff, buf);
462
        StackMapFrame frame = new StackMapFrame(getLabel(offset, labels),
463
                calculateLocals(cr.readClass(cr.header + 2, buf), // owner
464
                        cr.readUnsignedShort(methodOff), // method access
465
                        cr.readUTF8(methodOff + 2, buf), // method name
466
                        cr.readUTF8(methodOff + 4, buf)), // method desc
467
                Collections.EMPTY_LIST);
468
        frames.add(frame);
469
 
470
        // System.err.println( cr.readUTF8( methodOff + 2, buf));
471
        // System.err.println( offset +" delta:" + 0 +" : "+ frame);
472
 
473
        int size;
474
        if (isExtCodeSize) {
475
            size = cr.readInt(off);
476
            off += 4;
477
        } else {
478
            size = cr.readUnsignedShort(off);
479
            off += 2;
480
        }
481
 
482
        for (; size > 0; size--) {
483
            int tag = cr.readByte(off); // & 0xff;
484
            off++;
485
 
486
            List stack;
487
            List locals;
488
 
489
            int offsetDelta;
490
            if (tag < SAME_LOCALS_1_STACK_ITEM_FRAME) {  // SAME_FRAME
491
                offsetDelta = tag;
492
 
493
                locals = new ArrayList(frame.locals);
494
                stack = Collections.EMPTY_LIST;
495
 
496
            } else if (tag < RESERVED) {  // SAME_LOCALS_1_STACK_ITEM_FRAME
497
                offsetDelta = tag - SAME_LOCALS_1_STACK_ITEM_FRAME;
498
 
499
                locals = new ArrayList(frame.locals);
500
                stack = new ArrayList();
501
                // read verification_type_info stack[1];
502
                off = readType(stack, isExtCodeSize, cr, off, labels, buf);
503
 
504
            } else {
505
                if (isExtCodeSize) {
506
                    offsetDelta = cr.readInt(off);
507
                    off += 4;
508
                } else {
509
                    offsetDelta = cr.readUnsignedShort(off);
510
                    off += 2;
511
                }
512
 
513
                if (tag == SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) {  // SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED
514
                    locals = new ArrayList(frame.locals);
515
                    stack = new ArrayList();
516
                    // read verification_type_info stack[1];
517
                    off = readType(stack, isExtCodeSize, cr, off, labels, buf);
518
 
519
                } else if (tag >= CHOP_FRAME && tag < SAME_FRAME_EXTENDED) {  // CHOP_FRAME
520
                    stack = Collections.EMPTY_LIST;
521
 
522
                    int k = SAME_FRAME_EXTENDED - tag;
523
                    // copy locals from prev frame and chop last k
524
                    locals = new ArrayList(frame.locals.subList(0,
525
                            frame.locals.size() - k));
526
 
527
                } else if (tag == SAME_FRAME_EXTENDED) {  // SAME_FRAME_EXTENDED
528
                    stack = Collections.EMPTY_LIST;
529
                    locals = new ArrayList(frame.locals);
530
 
531
                } else if ( /* tag>=APPEND && */tag < FULL_FRAME) {  // APPEND_FRAME
532
                    stack = Collections.EMPTY_LIST;
533
 
534
                    // copy locals from prev frame and append new k
535
                    locals = new ArrayList(frame.locals);
536
                    for (int k = tag - SAME_FRAME_EXTENDED; k > 0; k--) {
537
                        off = readType(locals,
538
                                isExtCodeSize,
539
                                cr,
540
                                off,
541
                                labels,
542
                                buf);
543
                    }
544
 
545
                } else if (tag == FULL_FRAME) {  // FULL_FRAME
546
                    // read verification_type_info locals[number_of_locals];
547
                    locals = new ArrayList();
548
                    off = readTypes(locals,
549
                            isExtLocals,
550
                            isExtCodeSize,
551
                            cr,
552
                            off,
553
                            labels,
554
                            buf);
555
 
556
                    // read verification_type_info stack[number_of_stack_items];
557
                    stack = new ArrayList();
558
                    off = readTypes(stack,
559
                            isExtStack,
560
                            isExtCodeSize,
561
                            cr,
562
                            off,
563
                            labels,
564
                            buf);
565
 
566
                } else {
567
                    throw new RuntimeException("Unknown frame type " + tag
568
                            + " after offset " + offset);
569
 
570
                }
571
            }
572
 
573
            offset += offsetDelta;
574
 
575
            Label offsetLabel = getLabel(offset, labels);
576
 
577
            frame = new StackMapFrame(offsetLabel, locals, stack);
578
            frames.add(frame);
579
            // System.err.println( tag +" " + offset +" delta:" + offsetDelta +
580
            // " frameType:"+ frameType+" : "+ frame);
581
 
582
            offset++;
583
        }
584
 
585
        return new StackMapTableAttribute(frames);
586
    }
587
 
588
    protected ByteVector write(
589
        ClassWriter cw,
590
        byte[] code,
591
        int len,
592
        int maxStack,
593
        int maxLocals)
594
    {
595
        ByteVector bv = new ByteVector();
596
        // TODO verify this value (MAX_SHORT)
597
        boolean isExtCodeSize = code != null && code.length > MAX_SHORT;
598
        writeSize(frames.size() - 1, bv, isExtCodeSize);
599
 
600
        if (frames.size() < 2) {
601
            return bv;
602
        }
603
 
604
        boolean isExtLocals = maxLocals > MAX_SHORT;
605
        boolean isExtStack = maxStack > MAX_SHORT;
606
 
607
        // skip the first frame
608
        StackMapFrame frame = (StackMapFrame) frames.get(0);
609
        List locals = frame.locals;
610
        int offset = frame.label.getOffset();
611
 
612
        for (int i = 1; i < frames.size(); i++) {
613
            frame = (StackMapFrame) frames.get(i);
614
 
615
            List clocals = frame.locals;
616
            List cstack = frame.stack;
617
            int coffset = frame.label.getOffset();
618
 
619
            int clocalsSize = clocals.size();
620
            int cstackSize = cstack.size();
621
 
622
            int localsSize = locals.size();
623
 
624
            int delta = coffset - offset;
625
 
626
            int type = FULL_FRAME;
627
            int k = 0;
628
            if (cstackSize == 0) {
629
                k = clocalsSize - localsSize;
630
                switch (k) {
631
                    case -3:
632
                    case -2:
633
                    case -1:
634
                        type = CHOP_FRAME; // CHOP or FULL
635
                        localsSize = clocalsSize; // for full_frame check
636
                        break;
637
 
638
                    case 0:
639
                        // SAME, SAME_EXTENDED or FULL
640
                        type = delta < 64 ? SAME_FRAME : SAME_FRAME_EXTENDED;
641
                        break;
642
 
643
                    case 1:
644
                    case 2:
645
                    case 3:
646
                        type = APPEND_FRAME; // APPEND or FULL
647
                        break;
648
                }
649
            } else if (localsSize == clocalsSize && cstackSize == 1) {
650
                // SAME_LOCAL_1_STACK or FULL
651
                type = delta < 63
652
                        ? SAME_LOCALS_1_STACK_ITEM_FRAME
653
                        : SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED;
654
            }
655
 
656
            if (type != FULL_FRAME) {
657
                // verify if stack and locals are the same
658
                for (int j = 0; j < localsSize && type != FULL_FRAME; j++) {
659
                    if (!locals.get(j).equals(clocals.get(j)))
660
                        type = FULL_FRAME;
661
                }
662
            }
663
 
664
            switch (type) {
665
                case SAME_FRAME:
666
                    bv.putByte(delta);
667
                    break;
668
 
669
                case SAME_LOCALS_1_STACK_ITEM_FRAME:
670
                    bv.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME + delta);
671
                    writeTypeInfos(bv, cw, cstack, 0, 1);
672
                    break;
673
 
674
                case SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED:
675
                    bv.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED);
676
                    writeSize(delta, bv, isExtCodeSize);
677
                    writeTypeInfos(bv, cw, cstack, 0, 1);
678
                    break;
679
 
680
                case SAME_FRAME_EXTENDED:
681
                    bv.putByte(SAME_FRAME_EXTENDED);
682
                    writeSize(delta, bv, isExtCodeSize);
683
                    break;
684
 
685
                case CHOP_FRAME:
686
                    bv.putByte(SAME_FRAME_EXTENDED + k); // negative k
687
                    writeSize(delta, bv, isExtCodeSize);
688
                    break;
689
 
690
                case APPEND_FRAME:
691
                    bv.putByte(SAME_FRAME_EXTENDED + k); // positive k
692
                    writeSize(delta, bv, isExtCodeSize);
693
                    writeTypeInfos(bv,
694
                            cw,
695
                            clocals,
696
                            clocalsSize - 1,
697
                            clocalsSize);
698
                    break;
699
 
700
                case FULL_FRAME:
701
                    bv.putByte(FULL_FRAME);
702
                    writeSize(delta, bv, isExtCodeSize);
703
                    writeSize(clocalsSize, bv, isExtLocals);
704
                    writeTypeInfos(bv, cw, clocals, 0, clocalsSize);
705
                    writeSize(cstackSize, bv, isExtStack);
706
                    writeTypeInfos(bv, cw, cstack, 0, cstackSize);
707
                    break;
708
 
709
                default:
710
                    throw new RuntimeException();
711
            }
712
            offset = coffset + 1; // compensating non first offset
713
            locals = clocals;
714
        }
715
        return bv;
716
    }
717
 
718
    private void writeSize(int delta, ByteVector bv, boolean isExt) {
719
        if (isExt) {
720
            bv.putInt(delta);
721
        } else {
722
            bv.putShort(delta);
723
        }
724
    }
725
 
726
    private void writeTypeInfos(
727
        ByteVector bv,
728
        ClassWriter cw,
729
        List info,
730
        int start,
731
        int end)
732
    {
733
        for (int j = start; j < end; j++) {
734
            StackMapType typeInfo = (StackMapType) info.get(j);
735
            bv.putByte(typeInfo.getType());
736
 
737
            switch (typeInfo.getType()) {
738
                case StackMapType.ITEM_Object: //
739
                    bv.putShort(cw.newClass(typeInfo.getObject()));
740
                    break;
741
 
742
                case StackMapType.ITEM_Uninitialized: //
743
                    bv.putShort(typeInfo.getLabel().getOffset());
744
                    break;
745
 
746
            }
747
        }
748
    }
749
 
750
    public static int getMethodOff(ClassReader cr, int codeOff, char[] buf) {
751
        int off = cr.header + 6;
752
 
753
        int interfacesCount = cr.readUnsignedShort(off);
754
        off += 2 + interfacesCount * 2;
755
 
756
        int fieldsCount = cr.readUnsignedShort(off);
757
        off += 2;
758
        for (; fieldsCount > 0; --fieldsCount) {
759
            int attrCount = cr.readUnsignedShort(off + 6); // field attributes
760
            off += 8;
761
            for (; attrCount > 0; --attrCount) {
762
                off += 6 + cr.readInt(off + 2);
763
            }
764
        }
765
 
766
        int methodsCount = cr.readUnsignedShort(off);
767
        off += 2;
768
        for (; methodsCount > 0; --methodsCount) {
769
            int methodOff = off;
770
            int attrCount = cr.readUnsignedShort(off + 6); // method attributes
771
            off += 8;
772
            for (; attrCount > 0; --attrCount) {
773
                String attrName = cr.readUTF8(off, buf);
774
                off += 6;
775
                if (attrName.equals("Code")) {
776
                    if (codeOff == off) {
777
                        return methodOff;
778
                    }
779
                }
780
                off += cr.readInt(off - 4);
781
            }
782
        }
783
 
784
        return -1;
785
    }
786
 
787
    /**
788
     * Use method signature and access flags to resolve initial locals state.
789
     *
790
     * @param className name of the method's owner class.
791
     * @param access access flags of the method.
792
     * @param methodName name of the method.
793
     * @param methodDesc descriptor of the method.
794
     * @return list of <code>StackMapType</code> instances representing locals
795
     *         for an initial frame.
796
     */
797
    public static List calculateLocals(
798
        String className,
799
        int access,
800
        String methodName,
801
        String methodDesc)
802
    {
803
        List locals = new ArrayList();
804
 
805
        // TODO
806
        if ("<init>".equals(methodName)
807
                && !className.equals("java/lang/Object"))
808
        {
809
            StackMapType typeInfo = StackMapType.getTypeInfo(StackMapType.ITEM_UninitializedThis);
810
            typeInfo.setObject(className); // this
811
            locals.add(typeInfo);
812
        } else if ((access & Opcodes.ACC_STATIC) == 0) {
813
            StackMapType typeInfo = StackMapType.getTypeInfo(StackMapType.ITEM_Object);
814
            typeInfo.setObject(className); // this
815
            locals.add(typeInfo);
816
        }
817
 
818
        Type[] types = Type.getArgumentTypes(methodDesc);
819
        for (int i = 0; i < types.length; i++) {
820
            Type t = types[i];
821
            StackMapType smt;
822
            switch (t.getSort()) {
823
                case Type.LONG:
824
                    smt = StackMapType.getTypeInfo(StackMapType.ITEM_Long);
825
                    break;
826
                case Type.DOUBLE:
827
                    smt = StackMapType.getTypeInfo(StackMapType.ITEM_Double);
828
                    break;
829
 
830
                case Type.FLOAT:
831
                    smt = StackMapType.getTypeInfo(StackMapType.ITEM_Float);
832
                    break;
833
 
834
                case Type.ARRAY:
835
                case Type.OBJECT:
836
                    smt = StackMapType.getTypeInfo(StackMapType.ITEM_Object);
837
                    smt.setObject(t.getDescriptor()); // TODO verify name
838
                    break;
839
 
840
                default:
841
                    smt = StackMapType.getTypeInfo(StackMapType.ITEM_Integer);
842
                    break;
843
            }
844
        }
845
 
846
        return locals;
847
    }
848
 
849
    private int readTypes(
850
        List info,
851
        boolean isExt,
852
        boolean isExtCodeSize,
853
        ClassReader cr,
854
        int off,
855
        Label[] labels,
856
        char[] buf)
857
    {
858
        int n = 0;
859
        if (isExt) {
860
            n = cr.readInt(off);
861
            off += 4;
862
        } else {
863
            n = cr.readUnsignedShort(off);
864
            off += 2;
865
        }
866
 
867
        for (; n > 0; n--) {
868
            off = readType(info, isExtCodeSize, cr, off, labels, buf);
869
        }
870
        return off;
871
    }
872
 
873
    private int readType(
874
        List info,
875
        boolean isExtCodeSize,
876
        ClassReader cr,
877
        int off,
878
        Label[] labels,
879
        char[] buf)
880
    {
881
        int itemType = cr.readByte(off++);
882
        StackMapType typeInfo = StackMapType.getTypeInfo(itemType);
883
        info.add(typeInfo);
884
        switch (itemType) {
885
            // case StackMapType.ITEM_Long: //
886
            // case StackMapType.ITEM_Double: //
887
            // info.add(StackMapType.getTypeInfo(StackMapType.ITEM_Top));
888
            // break;
889
 
890
            case StackMapType.ITEM_Object: //
891
                typeInfo.setObject(cr.readClass(off, buf));
892
                off += 2;
893
                break;
894
 
895
            case StackMapType.ITEM_Uninitialized: //
896
                int offset;
897
                if (isExtCodeSize) {
898
                    offset = cr.readInt(off);
899
                    off += 4;
900
                } else {
901
                    offset = cr.readUnsignedShort(off);
902
                    off += 2;
903
                }
904
 
905
                typeInfo.setLabel(getLabel(offset, labels));
906
                break;
907
        }
908
        return off;
909
    }
910
 
911
    private Label getLabel(int offset, Label[] labels) {
912
        Label l = labels[offset];
913
        if (l != null) {
914
            return l;
915
        }
916
        return labels[offset] = new Label();
917
    }
918
 
919
    public String toString() {
920
        StringBuffer sb = new StringBuffer("StackMapTable[");
921
        for (int i = 0; i < frames.size(); i++) {
922
            sb.append('\n').append('[').append(frames.get(i)).append(']');
923
        }
924
        sb.append("\n]");
925
        return sb.toString();
926
    }
927
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.