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/] [ClassWriter.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;
31
 
32
/**
33
 * A {@link ClassVisitor} that generates classes in bytecode form. More
34
 * precisely this visitor generates a byte array conforming to the Java class
35
 * file format. It can be used alone, to generate a Java class "from scratch",
36
 * or with one or more {@link ClassReader ClassReader} and adapter class visitor
37
 * to generate a modified class from one or more existing Java classes.
38
 *
39
 * @author Eric Bruneton
40
 */
41
public class ClassWriter implements ClassVisitor {
42
 
43
    /**
44
     * The type of instructions without any argument.
45
     */
46
    final static int NOARG_INSN = 0;
47
 
48
    /**
49
     * The type of instructions with an signed byte argument.
50
     */
51
    final static int SBYTE_INSN = 1;
52
 
53
    /**
54
     * The type of instructions with an signed short argument.
55
     */
56
    final static int SHORT_INSN = 2;
57
 
58
    /**
59
     * The type of instructions with a local variable index argument.
60
     */
61
    final static int VAR_INSN = 3;
62
 
63
    /**
64
     * The type of instructions with an implicit local variable index argument.
65
     */
66
    final static int IMPLVAR_INSN = 4;
67
 
68
    /**
69
     * The type of instructions with a type descriptor argument.
70
     */
71
    final static int TYPE_INSN = 5;
72
 
73
    /**
74
     * The type of field and method invocations instructions.
75
     */
76
    final static int FIELDORMETH_INSN = 6;
77
 
78
    /**
79
     * The type of the INVOKEINTERFACE instruction.
80
     */
81
    final static int ITFMETH_INSN = 7;
82
 
83
    /**
84
     * The type of instructions with a 2 bytes bytecode offset label.
85
     */
86
    final static int LABEL_INSN = 8;
87
 
88
    /**
89
     * The type of instructions with a 4 bytes bytecode offset label.
90
     */
91
    final static int LABELW_INSN = 9;
92
 
93
    /**
94
     * The type of the LDC instruction.
95
     */
96
    final static int LDC_INSN = 10;
97
 
98
    /**
99
     * The type of the LDC_W and LDC2_W instructions.
100
     */
101
    final static int LDCW_INSN = 11;
102
 
103
    /**
104
     * The type of the IINC instruction.
105
     */
106
    final static int IINC_INSN = 12;
107
 
108
    /**
109
     * The type of the TABLESWITCH instruction.
110
     */
111
    final static int TABL_INSN = 13;
112
 
113
    /**
114
     * The type of the LOOKUPSWITCH instruction.
115
     */
116
    final static int LOOK_INSN = 14;
117
 
118
    /**
119
     * The type of the MULTIANEWARRAY instruction.
120
     */
121
    final static int MANA_INSN = 15;
122
 
123
    /**
124
     * The type of the WIDE instruction.
125
     */
126
    final static int WIDE_INSN = 16;
127
 
128
    /**
129
     * The instruction types of all JVM opcodes.
130
     */
131
    static byte[] TYPE;
132
 
133
    /**
134
     * The type of CONSTANT_Class constant pool items.
135
     */
136
    final static int CLASS = 7;
137
 
138
    /**
139
     * The type of CONSTANT_Fieldref constant pool items.
140
     */
141
    final static int FIELD = 9;
142
 
143
    /**
144
     * The type of CONSTANT_Methodref constant pool items.
145
     */
146
    final static int METH = 10;
147
 
148
    /**
149
     * The type of CONSTANT_InterfaceMethodref constant pool items.
150
     */
151
    final static int IMETH = 11;
152
 
153
    /**
154
     * The type of CONSTANT_String constant pool items.
155
     */
156
    final static int STR = 8;
157
 
158
    /**
159
     * The type of CONSTANT_Integer constant pool items.
160
     */
161
    final static int INT = 3;
162
 
163
    /**
164
     * The type of CONSTANT_Float constant pool items.
165
     */
166
    final static int FLOAT = 4;
167
 
168
    /**
169
     * The type of CONSTANT_Long constant pool items.
170
     */
171
    final static int LONG = 5;
172
 
173
    /**
174
     * The type of CONSTANT_Double constant pool items.
175
     */
176
    final static int DOUBLE = 6;
177
 
178
    /**
179
     * The type of CONSTANT_NameAndType constant pool items.
180
     */
181
    final static int NAME_TYPE = 12;
182
 
183
    /**
184
     * The type of CONSTANT_Utf8 constant pool items.
185
     */
186
    final static int UTF8 = 1;
187
 
188
    /**
189
     * The class reader from which this class writer was constructed, if any.
190
     */
191
    ClassReader cr;
192
 
193
    /**
194
     * Minor and major version numbers of the class to be generated.
195
     */
196
    int version;
197
 
198
    /**
199
     * Index of the next item to be added in the constant pool.
200
     */
201
    int index;
202
 
203
    /**
204
     * The constant pool of this class.
205
     */
206
    ByteVector pool;
207
 
208
    /**
209
     * The constant pool's hash table data.
210
     */
211
    Item[] items;
212
 
213
    /**
214
     * The threshold of the constant pool's hash table.
215
     */
216
    int threshold;
217
 
218
    /**
219
     * A reusable key used to look for items in the hash {@link #items items}.
220
     */
221
    Item key;
222
 
223
    /**
224
     * A reusable key used to look for items in the hash {@link #items items}.
225
     */
226
    Item key2;
227
 
228
    /**
229
     * A reusable key used to look for items in the hash {@link #items items}.
230
     */
231
    Item key3;
232
 
233
    /**
234
     * The access flags of this class.
235
     */
236
    private int access;
237
 
238
    /**
239
     * The constant pool item that contains the internal name of this class.
240
     */
241
    private int name;
242
 
243
    /**
244
     * The constant pool item that contains the signature of this class.
245
     */
246
    private int signature;
247
 
248
    /**
249
     * The constant pool item that contains the internal name of the super class
250
     * of this class.
251
     */
252
    private int superName;
253
 
254
    /**
255
     * Number of interfaces implemented or extended by this class or interface.
256
     */
257
    private int interfaceCount;
258
 
259
    /**
260
     * The interfaces implemented or extended by this class or interface. More
261
     * precisely, this array contains the indexes of the constant pool items
262
     * that contain the internal names of these interfaces.
263
     */
264
    private int[] interfaces;
265
 
266
    /**
267
     * The index of the constant pool item that contains the name of the source
268
     * file from which this class was compiled.
269
     */
270
    private int sourceFile;
271
 
272
    /**
273
     * The SourceDebug attribute of this class.
274
     */
275
    private ByteVector sourceDebug;
276
 
277
    /**
278
     * The constant pool item that contains the name of the enclosing class of
279
     * this class.
280
     */
281
    private int enclosingMethodOwner;
282
 
283
    /**
284
     * The constant pool item that contains the name and descriptor of the
285
     * enclosing method of this class.
286
     */
287
    private int enclosingMethod;
288
 
289
    /**
290
     * The runtime visible annotations of this class.
291
     */
292
    private AnnotationWriter anns;
293
 
294
    /**
295
     * The runtime invisible annotations of this class.
296
     */
297
    private AnnotationWriter ianns;
298
 
299
    /**
300
     * The non standard attributes of this class.
301
     */
302
    private Attribute attrs;
303
 
304
    /**
305
     * The number of entries in the InnerClasses attribute.
306
     */
307
    private int innerClassesCount;
308
 
309
    /**
310
     * The InnerClasses attribute.
311
     */
312
    private ByteVector innerClasses;
313
 
314
    /**
315
     * The fields of this class. These fields are stored in a linked list of
316
     * {@link FieldWriter} objects, linked to each other by their
317
     * {@link FieldWriter#next} field. This field stores the first element of
318
     * this list.
319
     */
320
    FieldWriter firstField;
321
 
322
    /**
323
     * The fields of this class. These fields are stored in a linked list of
324
     * {@link FieldWriter} objects, linked to each other by their
325
     * {@link FieldWriter#next} field. This field stores the last element of
326
     * this list.
327
     */
328
    FieldWriter lastField;
329
 
330
    /**
331
     * The methods of this class. These methods are stored in a linked list of
332
     * {@link MethodWriter} objects, linked to each other by their
333
     * {@link MethodWriter#next} field. This field stores the first element of
334
     * this list.
335
     */
336
    MethodWriter firstMethod;
337
 
338
    /**
339
     * The methods of this class. These methods are stored in a linked list of
340
     * {@link MethodWriter} objects, linked to each other by their
341
     * {@link MethodWriter#next} field. This field stores the last element of
342
     * this list.
343
     */
344
    MethodWriter lastMethod;
345
 
346
    /**
347
     * <tt>true</tt> if the maximum stack size and number of local variables
348
     * must be automatically computed.
349
     */
350
    private boolean computeMaxs;
351
 
352
    // ------------------------------------------------------------------------
353
    // Static initializer
354
    // ------------------------------------------------------------------------
355
 
356
    /**
357
     * Computes the instruction types of JVM opcodes.
358
     */
359
    static {
360
        int i;
361
        byte[] b = new byte[220];
362
        String s = "AAAAAAAAAAAAAAAABCKLLDDDDDEEEEEEEEEEEEEEEEEEEEAAAAAAAADD"
363
                + "DDDEEEEEEEEEEEEEEEEEEEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
364
                + "AAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAIIIIIIIIIIIIIIIIDNOAA"
365
                + "AAAAGGGGGGGHAFBFAAFFAAQPIIJJIIIIIIIIIIIIIIIIII";
366
        for (i = 0; i < b.length; ++i) {
367
            b[i] = (byte) (s.charAt(i) - 'A');
368
        }
369
        TYPE = b;
370
 
371
        // code to generate the above string
372
        //
373
        // // SBYTE_INSN instructions
374
        // b[Constants.NEWARRAY] = SBYTE_INSN;
375
        // b[Constants.BIPUSH] = SBYTE_INSN;
376
        //
377
        // // SHORT_INSN instructions
378
        // b[Constants.SIPUSH] = SHORT_INSN;
379
        //
380
        // // (IMPL)VAR_INSN instructions
381
        // b[Constants.RET] = VAR_INSN;
382
        // for (i = Constants.ILOAD; i <= Constants.ALOAD; ++i) {
383
        // b[i] = VAR_INSN;
384
        // }
385
        // for (i = Constants.ISTORE; i <= Constants.ASTORE; ++i) {
386
        // b[i] = VAR_INSN;
387
        // }
388
        // for (i = 26; i <= 45; ++i) { // ILOAD_0 to ALOAD_3
389
        // b[i] = IMPLVAR_INSN;
390
        // }
391
        // for (i = 59; i <= 78; ++i) { // ISTORE_0 to ASTORE_3
392
        // b[i] = IMPLVAR_INSN;
393
        // }
394
        //
395
        // // TYPE_INSN instructions
396
        // b[Constants.NEW] = TYPE_INSN;
397
        // b[Constants.ANEWARRAY] = TYPE_INSN;
398
        // b[Constants.CHECKCAST] = TYPE_INSN;
399
        // b[Constants.INSTANCEOF] = TYPE_INSN;
400
        //
401
        // // (Set)FIELDORMETH_INSN instructions
402
        // for (i = Constants.GETSTATIC; i <= Constants.INVOKESTATIC; ++i) {
403
        // b[i] = FIELDORMETH_INSN;
404
        // }
405
        // b[Constants.INVOKEINTERFACE] = ITFMETH_INSN;
406
        //
407
        // // LABEL(W)_INSN instructions
408
        // for (i = Constants.IFEQ; i <= Constants.JSR; ++i) {
409
        // b[i] = LABEL_INSN;
410
        // }
411
        // b[Constants.IFNULL] = LABEL_INSN;
412
        // b[Constants.IFNONNULL] = LABEL_INSN;
413
        // b[200] = LABELW_INSN; // GOTO_W
414
        // b[201] = LABELW_INSN; // JSR_W
415
        // // temporary opcodes used internally by ASM - see Label and
416
        // MethodWriter
417
        // for (i = 202; i < 220; ++i) {
418
        // b[i] = LABEL_INSN;
419
        // }
420
        //
421
        // // LDC(_W) instructions
422
        // b[Constants.LDC] = LDC_INSN;
423
        // b[19] = LDCW_INSN; // LDC_W
424
        // b[20] = LDCW_INSN; // LDC2_W
425
        //
426
        // // special instructions
427
        // b[Constants.IINC] = IINC_INSN;
428
        // b[Constants.TABLESWITCH] = TABL_INSN;
429
        // b[Constants.LOOKUPSWITCH] = LOOK_INSN;
430
        // b[Constants.MULTIANEWARRAY] = MANA_INSN;
431
        // b[196] = WIDE_INSN; // WIDE
432
        //
433
        // for (i = 0; i < b.length; ++i) {
434
        // System.err.print((char)('A' + b[i]));
435
        // }
436
        // System.err.println();
437
    }
438
 
439
    // ------------------------------------------------------------------------
440
    // Constructor
441
    // ------------------------------------------------------------------------
442
 
443
    /**
444
     * Constructs a new {@link ClassWriter ClassWriter} object.
445
     *
446
     * @param computeMaxs <tt>true</tt> if the maximum stack size and the
447
     *        maximum number of local variables must be automatically computed.
448
     *        If this flag is <tt>true</tt>, then the arguments of the
449
     *        {@link MethodVisitor#visitMaxs visitMaxs} method of the
450
     *        {@link MethodVisitor} returned by the
451
     *        {@link #visitMethod visitMethod} method will be ignored, and
452
     *        computed automatically from the signature and the bytecode of each
453
     *        method.
454
     */
455
    public ClassWriter(final boolean computeMaxs) {
456
        this(computeMaxs, false);
457
    }
458
 
459
    /**
460
     * Constructs a new {@link ClassWriter} object.
461
     *
462
     * @param computeMaxs <tt>true</tt> if the maximum stack size and the
463
     *        maximum number of local variables must be automatically computed.
464
     *        If this flag is <tt>true</tt>, then the arguments of the
465
     *        {@link MethodVisitor#visitMaxs visitMaxs} method of the
466
     *        {@link MethodVisitor} returned by the
467
     *        {@link #visitMethod visitMethod} method will be ignored, and
468
     *        computed automatically from the signature and the bytecode of each
469
     *        method.
470
     * @param skipUnknownAttributes <b>Deprecated</b>. The value of this
471
     *        parameter is ignored.
472
     */
473
    public ClassWriter(
474
        final boolean computeMaxs,
475
        final boolean skipUnknownAttributes)
476
    {
477
        index = 1;
478
        pool = new ByteVector();
479
        items = new Item[256];
480
        threshold = (int) (0.75d * items.length);
481
        key = new Item();
482
        key2 = new Item();
483
        key3 = new Item();
484
        this.computeMaxs = computeMaxs;
485
    }
486
 
487
    /**
488
     * Constructs a new {@link ClassWriter} object and enables optimizations for
489
     * "mostly add" bytecode transformations. These optimizations are the
490
     * following:
491
     *
492
     * <ul> <li>The constant pool from the original class is copied as is in
493
     * the new class, which saves time. New constant pool entries will be added
494
     * at the end if necessary, but unused constant pool entries <i>won't be
495
     * removed</i>.</li> <li>Methods that are not transformed are copied as
496
     * is in the new class, directly from the original class bytecode (i.e.
497
     * without emitting visit events for all the method instructions), which
498
     * saves a <i>lot</i> of time. Untransformed methods are detected by the
499
     * fact that the {@link ClassReader} receives {@link MethodVisitor} objects
500
     * that come from a {@link ClassWriter} (and not from a custom
501
     * {@link ClassAdapter} or any other {@link ClassVisitor} instance).</li>
502
     * </ul>
503
     *
504
     * @param classReader the {@link ClassReader} used to read the original
505
     *        class. It will be used to copy the entire constant pool from the
506
     *        original class and also to copy other fragments of original
507
     *        bytecode where applicable.
508
     * @param computeMaxs <tt>true</tt> if the maximum stack size and the
509
     *        maximum number of local variables must be automatically computed.
510
     *        If this flag is <tt>true</tt>, then the arguments of the
511
     *        {@link MethodVisitor#visitMaxs visitMaxs} method of the
512
     *        {@link MethodVisitor} returned by the
513
     *        {@link #visitMethod visitMethod} method will be ignored, and
514
     *        computed automatically from the signature and the bytecode of each
515
     *        method.
516
     */
517
    public ClassWriter(
518
        final ClassReader classReader,
519
        final boolean computeMaxs)
520
    {
521
        this(computeMaxs, false);
522
        classReader.copyPool(this);
523
        this.cr = classReader;
524
    }
525
 
526
    // ------------------------------------------------------------------------
527
    // Implementation of the ClassVisitor interface
528
    // ------------------------------------------------------------------------
529
 
530
    public void visit(
531
        final int version,
532
        final int access,
533
        final String name,
534
        final String signature,
535
        final String superName,
536
        final String[] interfaces)
537
    {
538
        this.version = version;
539
        this.access = access;
540
        this.name = newClass(name);
541
        if (signature != null) {
542
            this.signature = newUTF8(signature);
543
        }
544
        this.superName = superName == null ? 0 : newClass(superName);
545
        if (interfaces != null && interfaces.length > 0) {
546
            interfaceCount = interfaces.length;
547
            this.interfaces = new int[interfaceCount];
548
            for (int i = 0; i < interfaceCount; ++i) {
549
                this.interfaces[i] = newClass(interfaces[i]);
550
            }
551
        }
552
    }
553
 
554
    public void visitSource(final String file, final String debug) {
555
        if (file != null) {
556
            sourceFile = newUTF8(file);
557
        }
558
        if (debug != null) {
559
            sourceDebug = new ByteVector().putUTF8(debug);
560
        }
561
    }
562
 
563
    public void visitOuterClass(
564
        final String owner,
565
        final String name,
566
        final String desc)
567
    {
568
        enclosingMethodOwner = newClass(owner);
569
        if (name != null && desc != null) {
570
            enclosingMethod = newNameType(name, desc);
571
        }
572
    }
573
 
574
    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
575
        ByteVector bv = new ByteVector();
576
        // write type, and reserve space for values count
577
        bv.putShort(newUTF8(desc)).putShort(0);
578
        AnnotationWriter aw = new AnnotationWriter(this, true, bv, bv, 2);
579
        if (visible) {
580
            aw.next = anns;
581
            anns = aw;
582
        } else {
583
            aw.next = ianns;
584
            ianns = aw;
585
        }
586
        return aw;
587
    }
588
 
589
    public void visitAttribute(final Attribute attr) {
590
        attr.next = attrs;
591
        attrs = attr;
592
    }
593
 
594
    public void visitInnerClass(
595
        final String name,
596
        final String outerName,
597
        final String innerName,
598
        final int access)
599
    {
600
        if (innerClasses == null) {
601
            innerClasses = new ByteVector();
602
        }
603
        ++innerClassesCount;
604
        innerClasses.putShort(name == null ? 0 : newClass(name));
605
        innerClasses.putShort(outerName == null ? 0 : newClass(outerName));
606
        innerClasses.putShort(innerName == null ? 0 : newUTF8(innerName));
607
        innerClasses.putShort(access);
608
    }
609
 
610
    public FieldVisitor visitField(
611
        final int access,
612
        final String name,
613
        final String desc,
614
        final String signature,
615
        final Object value)
616
    {
617
        return new FieldWriter(this, access, name, desc, signature, value);
618
    }
619
 
620
    public MethodVisitor visitMethod(
621
        final int access,
622
        final String name,
623
        final String desc,
624
        final String signature,
625
        final String[] exceptions)
626
    {
627
        return new MethodWriter(this,
628
                access,
629
                name,
630
                desc,
631
                signature,
632
                exceptions,
633
                computeMaxs);
634
    }
635
 
636
    public void visitEnd() {
637
    }
638
 
639
    // ------------------------------------------------------------------------
640
    // Other public methods
641
    // ------------------------------------------------------------------------
642
 
643
    /**
644
     * Returns the bytecode of the class that was build with this class writer.
645
     *
646
     * @return the bytecode of the class that was build with this class writer.
647
     */
648
    public byte[] toByteArray() {
649
        // computes the real size of the bytecode of this class
650
        int size = 24 + 2 * interfaceCount;
651
        int nbFields = 0;
652
        FieldWriter fb = firstField;
653
        while (fb != null) {
654
            ++nbFields;
655
            size += fb.getSize();
656
            fb = fb.next;
657
        }
658
        int nbMethods = 0;
659
        MethodWriter mb = firstMethod;
660
        while (mb != null) {
661
            ++nbMethods;
662
            size += mb.getSize();
663
            mb = mb.next;
664
        }
665
        int attributeCount = 0;
666
        if (signature != 0) {
667
            ++attributeCount;
668
            size += 8;
669
            newUTF8("Signature");
670
        }
671
        if (sourceFile != 0) {
672
            ++attributeCount;
673
            size += 8;
674
            newUTF8("SourceFile");
675
        }
676
        if (sourceDebug != null) {
677
            ++attributeCount;
678
            size += sourceDebug.length + 4;
679
            newUTF8("SourceDebugExtension");
680
        }
681
        if (enclosingMethodOwner != 0) {
682
            ++attributeCount;
683
            size += 10;
684
            newUTF8("EnclosingMethod");
685
        }
686
        if ((access & Opcodes.ACC_DEPRECATED) != 0) {
687
            ++attributeCount;
688
            size += 6;
689
            newUTF8("Deprecated");
690
        }
691
        if ((access & Opcodes.ACC_SYNTHETIC) != 0
692
                && (version & 0xffff) < Opcodes.V1_5)
693
        {
694
            ++attributeCount;
695
            size += 6;
696
            newUTF8("Synthetic");
697
        }
698
        if (version == Opcodes.V1_4) {
699
            if ((access & Opcodes.ACC_ANNOTATION) != 0) {
700
                ++attributeCount;
701
                size += 6;
702
                newUTF8("Annotation");
703
            }
704
            if ((access & Opcodes.ACC_ENUM) != 0) {
705
                ++attributeCount;
706
                size += 6;
707
                newUTF8("Enum");
708
            }
709
        }
710
        if (innerClasses != null) {
711
            ++attributeCount;
712
            size += 8 + innerClasses.length;
713
            newUTF8("InnerClasses");
714
        }
715
        if (anns != null) {
716
            ++attributeCount;
717
            size += 8 + anns.getSize();
718
            newUTF8("RuntimeVisibleAnnotations");
719
        }
720
        if (ianns != null) {
721
            ++attributeCount;
722
            size += 8 + ianns.getSize();
723
            newUTF8("RuntimeInvisibleAnnotations");
724
        }
725
        if (attrs != null) {
726
            attributeCount += attrs.getCount();
727
            size += attrs.getSize(this, null, 0, -1, -1);
728
        }
729
        size += pool.length;
730
        // allocates a byte vector of this size, in order to avoid unnecessary
731
        // arraycopy operations in the ByteVector.enlarge() method
732
        ByteVector out = new ByteVector(size);
733
        out.putInt(0xCAFEBABE).putInt(version);
734
        out.putShort(index).putByteArray(pool.data, 0, pool.length);
735
        out.putShort(access).putShort(name).putShort(superName);
736
        out.putShort(interfaceCount);
737
        for (int i = 0; i < interfaceCount; ++i) {
738
            out.putShort(interfaces[i]);
739
        }
740
        out.putShort(nbFields);
741
        fb = firstField;
742
        while (fb != null) {
743
            fb.put(out);
744
            fb = fb.next;
745
        }
746
        out.putShort(nbMethods);
747
        mb = firstMethod;
748
        while (mb != null) {
749
            mb.put(out);
750
            mb = mb.next;
751
        }
752
        out.putShort(attributeCount);
753
        if (signature != 0) {
754
            out.putShort(newUTF8("Signature")).putInt(2).putShort(signature);
755
        }
756
        if (sourceFile != 0) {
757
            out.putShort(newUTF8("SourceFile")).putInt(2).putShort(sourceFile);
758
        }
759
        if (sourceDebug != null) {
760
            int len = sourceDebug.length - 2;
761
            out.putShort(newUTF8("SourceDebugExtension")).putInt(len);
762
            out.putByteArray(sourceDebug.data, 2, len);
763
        }
764
        if (enclosingMethodOwner != 0) {
765
            out.putShort(newUTF8("EnclosingMethod")).putInt(4);
766
            out.putShort(enclosingMethodOwner).putShort(enclosingMethod);
767
        }
768
        if ((access & Opcodes.ACC_DEPRECATED) != 0) {
769
            out.putShort(newUTF8("Deprecated")).putInt(0);
770
        }
771
        if ((access & Opcodes.ACC_SYNTHETIC) != 0
772
                && (version & 0xffff) < Opcodes.V1_5)
773
        {
774
            out.putShort(newUTF8("Synthetic")).putInt(0);
775
        }
776
        if (version == Opcodes.V1_4) {
777
            if ((access & Opcodes.ACC_ANNOTATION) != 0) {
778
                out.putShort(newUTF8("Annotation")).putInt(0);
779
            }
780
            if ((access & Opcodes.ACC_ENUM) != 0) {
781
                out.putShort(newUTF8("Enum")).putInt(0);
782
            }
783
        }
784
        if (innerClasses != null) {
785
            out.putShort(newUTF8("InnerClasses"));
786
            out.putInt(innerClasses.length + 2).putShort(innerClassesCount);
787
            out.putByteArray(innerClasses.data, 0, innerClasses.length);
788
        }
789
        if (anns != null) {
790
            out.putShort(newUTF8("RuntimeVisibleAnnotations"));
791
            anns.put(out);
792
        }
793
        if (ianns != null) {
794
            out.putShort(newUTF8("RuntimeInvisibleAnnotations"));
795
            ianns.put(out);
796
        }
797
        if (attrs != null) {
798
            attrs.put(this, null, 0, -1, -1, out);
799
        }
800
        return out.data;
801
    }
802
 
803
    // ------------------------------------------------------------------------
804
    // Utility methods: constant pool management
805
    // ------------------------------------------------------------------------
806
 
807
    /**
808
     * Adds a number or string constant to the constant pool of the class being
809
     * build. Does nothing if the constant pool already contains a similar item.
810
     *
811
     * @param cst the value of the constant to be added to the constant pool.
812
     *        This parameter must be an {@link Integer}, a {@link Float}, a
813
     *        {@link Long}, a {@link Double}, a {@link String} or a
814
     *        {@link Type}.
815
     * @return a new or already existing constant item with the given value.
816
     */
817
    Item newConstItem(final Object cst) {
818
        if (cst instanceof Integer) {
819
            int val = ((Integer) cst).intValue();
820
            return newInteger(val);
821
        } else if (cst instanceof Byte) {
822
            int val = ((Byte) cst).intValue();
823
            return newInteger(val);
824
        } else if (cst instanceof Character) {
825
            int val = ((Character) cst).charValue();
826
            return newInteger(val);
827
        } else if (cst instanceof Short) {
828
            int val = ((Short) cst).intValue();
829
            return newInteger(val);
830
        } else if (cst instanceof Boolean) {
831
            int val = ((Boolean) cst).booleanValue() ? 1 : 0;
832
            return newInteger(val);
833
        } else if (cst instanceof Float) {
834
            float val = ((Float) cst).floatValue();
835
            return newFloat(val);
836
        } else if (cst instanceof Long) {
837
            long val = ((Long) cst).longValue();
838
            return newLong(val);
839
        } else if (cst instanceof Double) {
840
            double val = ((Double) cst).doubleValue();
841
            return newDouble(val);
842
        } else if (cst instanceof String) {
843
            return newString((String) cst);
844
        } else if (cst instanceof Type) {
845
            Type t = (Type) cst;
846
            return newClassItem(t.getSort() == Type.OBJECT
847
                    ? t.getInternalName()
848
                    : t.getDescriptor());
849
        } else {
850
            throw new IllegalArgumentException("value " + cst);
851
        }
852
    }
853
 
854
    /**
855
     * Adds a number or string constant to the constant pool of the class being
856
     * build. Does nothing if the constant pool already contains a similar item.
857
     * <i>This method is intended for {@link Attribute} sub classes, and is
858
     * normally not needed by class generators or adapters.</i>
859
     *
860
     * @param cst the value of the constant to be added to the constant pool.
861
     *        This parameter must be an {@link Integer}, a {@link Float}, a
862
     *        {@link Long}, a {@link Double} or a {@link String}.
863
     * @return the index of a new or already existing constant item with the
864
     *         given value.
865
     */
866
    public int newConst(final Object cst) {
867
        return newConstItem(cst).index;
868
    }
869
 
870
    /**
871
     * Adds an UTF8 string to the constant pool of the class being build. Does
872
     * nothing if the constant pool already contains a similar item. <i>This
873
     * method is intended for {@link Attribute} sub classes, and is normally not
874
     * needed by class generators or adapters.</i>
875
     *
876
     * @param value the String value.
877
     * @return the index of a new or already existing UTF8 item.
878
     */
879
    public int newUTF8(final String value) {
880
        key.set(UTF8, value, null, null);
881
        Item result = get(key);
882
        if (result == null) {
883
            pool.putByte(UTF8).putUTF8(value);
884
            result = new Item(index++, key);
885
            put(result);
886
        }
887
        return result.index;
888
    }
889
 
890
    /**
891
     * Adds a class reference to the constant pool of the class being build.
892
     * Does nothing if the constant pool already contains a similar item.
893
     * <i>This method is intended for {@link Attribute} sub classes, and is
894
     * normally not needed by class generators or adapters.</i>
895
     *
896
     * @param value the internal name of the class.
897
     * @return the index of a new or already existing class reference item.
898
     */
899
    public int newClass(final String value) {
900
        return newClassItem(value).index;
901
    }
902
 
903
    /**
904
     * Adds a class reference to the constant pool of the class being build.
905
     * Does nothing if the constant pool already contains a similar item.
906
     * <i>This method is intended for {@link Attribute} sub classes, and is
907
     * normally not needed by class generators or adapters.</i>
908
     *
909
     * @param value the internal name of the class.
910
     * @return a new or already existing class reference item.
911
     */
912
    private Item newClassItem(final String value) {
913
        key2.set(CLASS, value, null, null);
914
        Item result = get(key2);
915
        if (result == null) {
916
            pool.put12(CLASS, newUTF8(value));
917
            result = new Item(index++, key2);
918
            put(result);
919
        }
920
        return result;
921
    }
922
 
923
    /**
924
     * Adds a field reference to the constant pool of the class being build.
925
     * Does nothing if the constant pool already contains a similar item.
926
     * <i>This method is intended for {@link Attribute} sub classes, and is
927
     * normally not needed by class generators or adapters.</i>
928
     *
929
     * @param owner the internal name of the field's owner class.
930
     * @param name the field's name.
931
     * @param desc the field's descriptor.
932
     * @return the index of a new or already existing field reference item.
933
     */
934
    public int newField(final String owner, final String name, final String desc)
935
    {
936
        key3.set(FIELD, owner, name, desc);
937
        Item result = get(key3);
938
        if (result == null) {
939
            put122(FIELD, newClass(owner), newNameType(name, desc));
940
            result = new Item(index++, key3);
941
            put(result);
942
        }
943
        return result.index;
944
    }
945
 
946
    /**
947
     * Adds a method reference to the constant pool of the class being build.
948
     * Does nothing if the constant pool already contains a similar item.
949
     *
950
     * @param owner the internal name of the method's owner class.
951
     * @param name the method's name.
952
     * @param desc the method's descriptor.
953
     * @param itf <tt>true</tt> if <tt>owner</tt> is an interface.
954
     * @return a new or already existing method reference item.
955
     */
956
    Item newMethodItem(
957
        final String owner,
958
        final String name,
959
        final String desc,
960
        final boolean itf)
961
    {
962
        int type = itf ? IMETH : METH;
963
        key3.set(type, owner, name, desc);
964
        Item result = get(key3);
965
        if (result == null) {
966
            put122(type, newClass(owner), newNameType(name, desc));
967
            result = new Item(index++, key3);
968
            put(result);
969
        }
970
        return result;
971
    }
972
 
973
    /**
974
     * Adds a method reference to the constant pool of the class being build.
975
     * Does nothing if the constant pool already contains a similar item.
976
     * <i>This method is intended for {@link Attribute} sub classes, and is
977
     * normally not needed by class generators or adapters.</i>
978
     *
979
     * @param owner the internal name of the method's owner class.
980
     * @param name the method's name.
981
     * @param desc the method's descriptor.
982
     * @param itf <tt>true</tt> if <tt>owner</tt> is an interface.
983
     * @return the index of a new or already existing method reference item.
984
     */
985
    public int newMethod(
986
        final String owner,
987
        final String name,
988
        final String desc,
989
        final boolean itf)
990
    {
991
        return newMethodItem(owner, name, desc, itf).index;
992
    }
993
 
994
    /**
995
     * Adds an integer to the constant pool of the class being build. Does
996
     * nothing if the constant pool already contains a similar item.
997
     *
998
     * @param value the int value.
999
     * @return a new or already existing int item.
1000
     */
1001
    Item newInteger(final int value) {
1002
        key.set(value);
1003
        Item result = get(key);
1004
        if (result == null) {
1005
            pool.putByte(INT).putInt(value);
1006
            result = new Item(index++, key);
1007
            put(result);
1008
        }
1009
        return result;
1010
    }
1011
 
1012
    /**
1013
     * Adds a float to the constant pool of the class being build. Does nothing
1014
     * if the constant pool already contains a similar item.
1015
     *
1016
     * @param value the float value.
1017
     * @return a new or already existing float item.
1018
     */
1019
    Item newFloat(final float value) {
1020
        key.set(value);
1021
        Item result = get(key);
1022
        if (result == null) {
1023
            pool.putByte(FLOAT).putInt(Float.floatToIntBits(value));
1024
            result = new Item(index++, key);
1025
            put(result);
1026
        }
1027
        return result;
1028
    }
1029
 
1030
    /**
1031
     * Adds a long to the constant pool of the class being build. Does nothing
1032
     * if the constant pool already contains a similar item.
1033
     *
1034
     * @param value the long value.
1035
     * @return a new or already existing long item.
1036
     */
1037
    Item newLong(final long value) {
1038
        key.set(value);
1039
        Item result = get(key);
1040
        if (result == null) {
1041
            pool.putByte(LONG).putLong(value);
1042
            result = new Item(index, key);
1043
            put(result);
1044
            index += 2;
1045
        }
1046
        return result;
1047
    }
1048
 
1049
    /**
1050
     * Adds a double to the constant pool of the class being build. Does nothing
1051
     * if the constant pool already contains a similar item.
1052
     *
1053
     * @param value the double value.
1054
     * @return a new or already existing double item.
1055
     */
1056
    Item newDouble(final double value) {
1057
        key.set(value);
1058
        Item result = get(key);
1059
        if (result == null) {
1060
            pool.putByte(DOUBLE).putLong(Double.doubleToLongBits(value));
1061
            result = new Item(index, key);
1062
            put(result);
1063
            index += 2;
1064
        }
1065
        return result;
1066
    }
1067
 
1068
    /**
1069
     * Adds a string to the constant pool of the class being build. Does nothing
1070
     * if the constant pool already contains a similar item.
1071
     *
1072
     * @param value the String value.
1073
     * @return a new or already existing string item.
1074
     */
1075
    private Item newString(final String value) {
1076
        key2.set(STR, value, null, null);
1077
        Item result = get(key2);
1078
        if (result == null) {
1079
            pool.put12(STR, newUTF8(value));
1080
            result = new Item(index++, key2);
1081
            put(result);
1082
        }
1083
        return result;
1084
    }
1085
 
1086
    /**
1087
     * Adds a name and type to the constant pool of the class being build. Does
1088
     * nothing if the constant pool already contains a similar item. <i>This
1089
     * method is intended for {@link Attribute} sub classes, and is normally not
1090
     * needed by class generators or adapters.</i>
1091
     *
1092
     * @param name a name.
1093
     * @param desc a type descriptor.
1094
     * @return the index of a new or already existing name and type item.
1095
     */
1096
    public int newNameType(final String name, final String desc) {
1097
        key2.set(NAME_TYPE, name, desc, null);
1098
        Item result = get(key2);
1099
        if (result == null) {
1100
            put122(NAME_TYPE, newUTF8(name), newUTF8(desc));
1101
            result = new Item(index++, key2);
1102
            put(result);
1103
        }
1104
        return result.index;
1105
    }
1106
 
1107
    /**
1108
     * Returns the constant pool's hash table item which is equal to the given
1109
     * item.
1110
     *
1111
     * @param key a constant pool item.
1112
     * @return the constant pool's hash table item which is equal to the given
1113
     *         item, or <tt>null</tt> if there is no such item.
1114
     */
1115
    private Item get(final Item key) {
1116
        Item i = items[key.hashCode % items.length];
1117
        while (i != null && !key.isEqualTo(i)) {
1118
            i = i.next;
1119
        }
1120
        return i;
1121
    }
1122
 
1123
    /**
1124
     * Puts the given item in the constant pool's hash table. The hash table
1125
     * <i>must</i> not already contains this item.
1126
     *
1127
     * @param i the item to be added to the constant pool's hash table.
1128
     */
1129
    private void put(final Item i) {
1130
        if (index > threshold) {
1131
            int ll = items.length;
1132
            int nl = ll * 2 + 1;
1133
            Item[] newItems = new Item[nl];
1134
            for (int l = ll - 1; l >= 0; --l) {
1135
                Item j = items[l];
1136
                while (j != null) {
1137
                    int index = j.hashCode % newItems.length;
1138
                    Item k = j.next;
1139
                    j.next = newItems[index];
1140
                    newItems[index] = j;
1141
                    j = k;
1142
                }
1143
            }
1144
            items = newItems;
1145
            threshold = (int) (nl * 0.75);
1146
        }
1147
        int index = i.hashCode % items.length;
1148
        i.next = items[index];
1149
        items[index] = i;
1150
    }
1151
 
1152
    /**
1153
     * Puts one byte and two shorts into the constant pool.
1154
     *
1155
     * @param b a byte.
1156
     * @param s1 a short.
1157
     * @param s2 another short.
1158
     */
1159
    private void put122(final int b, final int s1, final int s2) {
1160
        pool.put12(b, s1).putShort(s2);
1161
    }
1162
}

powered by: WebSVN 2.1.0

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