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/] [commons/] [AdviceAdapter.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.commons;
31
 
32
import java.util.ArrayList;
33
import java.util.HashMap;
34
 
35
import org.objectweb.asm.Label;
36
import org.objectweb.asm.MethodVisitor;
37
import org.objectweb.asm.Opcodes;
38
import org.objectweb.asm.Type;
39
 
40
/**
41
 * A <code>MethodAdapter</code> to dispatch method body instruction
42
 * <p>
43
 * The behavior is like this:
44
 * <ol>
45
 *
46
 * <li>as long as the INVOKESPECIAL for the object initialization has not been
47
 *     reached, every bytecode instruction is dispatched in the ctor code visitor</li>
48
 *
49
 * <li>when this one is reached, it is only added in the ctor code visitor and
50
 *     a JP invoke is added</li>
51
 * <li>after that, only the other code visitor receives the instructions</li>
52
 *
53
 * </ol>
54
 *
55
 * @author Eugene Kuleshov
56
 * @author Eric Bruneton
57
 */
58
public abstract class AdviceAdapter extends GeneratorAdapter implements Opcodes {
59
    private static final Object THIS = new Object();
60
    private static final Object OTHER = new Object();
61
 
62
    protected int methodAccess;
63
    protected String methodDesc;
64
 
65
    private boolean constructor;
66
    private boolean superInitialized;
67
    private ArrayList stackFrame;
68
    private HashMap branches;
69
 
70
 
71
    /**
72
     * Creates a new {@link AdviceAdapter}.
73
     *
74
     * @param mv the method visitor to which this adapter delegates calls.
75
     * @param access the method's access flags (see {@link Opcodes}).
76
     * @param name the method's name.
77
     * @param desc the method's descriptor (see {@link Type Type}).
78
     */
79
    public AdviceAdapter(MethodVisitor mv, int access, String name, String desc) {
80
        super(mv, access, name, desc);
81
        methodAccess = access;
82
        methodDesc = desc;
83
 
84
        constructor = "<init>".equals(name);
85
        if (!constructor) {
86
            superInitialized = true;
87
            onMethodEnter();
88
        } else {
89
            stackFrame = new ArrayList();
90
            branches = new HashMap();
91
        }
92
    }
93
 
94
    public void visitLabel(Label label) {
95
        mv.visitLabel(label);
96
 
97
        if (constructor && branches != null) {
98
            ArrayList frame = (ArrayList) branches.get(label);
99
            if (frame != null) {
100
                stackFrame = frame;
101
                branches.remove(label);
102
            }
103
        }
104
    }
105
 
106
    public void visitInsn(int opcode) {
107
        if (constructor) {
108
            switch (opcode) {
109
                case RETURN: // empty stack
110
                    onMethodExit(opcode);
111
                    break;
112
 
113
                case IRETURN: // 1 before n/a after
114
                case FRETURN: // 1 before n/a after
115
                case ARETURN: // 1 before n/a after
116
                case ATHROW: // 1 before n/a after
117
                    popValue();
118
                    popValue();
119
                    onMethodExit(opcode);
120
                    break;
121
 
122
                case LRETURN: // 2 before n/a after
123
                case DRETURN: // 2 before n/a after
124
                    popValue();
125
                    popValue();
126
                    onMethodExit(opcode);
127
                    break;
128
 
129
                case NOP:
130
                case LALOAD: // remove 2 add 2
131
                case DALOAD: // remove 2 add 2
132
                case LNEG:
133
                case DNEG:
134
                case FNEG:
135
                case INEG:
136
                case L2D:
137
                case D2L:
138
                case F2I:
139
                case I2B:
140
                case I2C:
141
                case I2S:
142
                case I2F:
143
                case Opcodes.ARRAYLENGTH:
144
                    break;
145
 
146
                case ACONST_NULL:
147
                case ICONST_M1:
148
                case ICONST_0:
149
                case ICONST_1:
150
                case ICONST_2:
151
                case ICONST_3:
152
                case ICONST_4:
153
                case ICONST_5:
154
                case FCONST_0:
155
                case FCONST_1:
156
                case FCONST_2:
157
                case F2L: // 1 before 2 after
158
                case F2D:
159
                case I2L:
160
                case I2D:
161
                    pushValue(OTHER);
162
                    break;
163
 
164
                case LCONST_0:
165
                case LCONST_1:
166
                case DCONST_0:
167
                case DCONST_1:
168
                    pushValue(OTHER);
169
                    pushValue(OTHER);
170
                    break;
171
 
172
                case IALOAD: // remove 2 add 1
173
                case FALOAD: // remove 2 add 1
174
                case AALOAD: // remove 2 add 1
175
                case BALOAD: // remove 2 add 1
176
                case CALOAD: // remove 2 add 1
177
                case SALOAD: // remove 2 add 1
178
                case POP:
179
                case IADD:
180
                case FADD:
181
                case ISUB:
182
                case LSHL: // 3 before 2 after
183
                case LSHR: // 3 before 2 after
184
                case LUSHR: // 3 before 2 after
185
                case L2I: // 2 before 1 after
186
                case L2F: // 2 before 1 after
187
                case D2I: // 2 before 1 after
188
                case D2F: // 2 before 1 after
189
                case FSUB:
190
                case FMUL:
191
                case FDIV:
192
                case FREM:
193
                case FCMPL: // 2 before 1 after
194
                case FCMPG: // 2 before 1 after
195
                case IMUL:
196
                case IDIV:
197
                case IREM:
198
                case ISHL:
199
                case ISHR:
200
                case IUSHR:
201
                case IAND:
202
                case IOR:
203
                case IXOR:
204
                case MONITORENTER:
205
                case MONITOREXIT:
206
                    popValue();
207
                    break;
208
 
209
                case POP2:
210
                case LSUB:
211
                case LMUL:
212
                case LDIV:
213
                case LREM:
214
                case LADD:
215
                case LAND:
216
                case LOR:
217
                case LXOR:
218
                case DADD:
219
                case DMUL:
220
                case DSUB:
221
                case DDIV:
222
                case DREM:
223
                    popValue();
224
                    popValue();
225
                    break;
226
 
227
                case IASTORE:
228
                case FASTORE:
229
                case AASTORE:
230
                case BASTORE:
231
                case CASTORE:
232
                case SASTORE:
233
                case LCMP: // 4 before 1 after
234
                case DCMPL:
235
                case DCMPG:
236
                    popValue();
237
                    popValue();
238
                    popValue();
239
                    break;
240
 
241
                case LASTORE:
242
                case DASTORE:
243
                    popValue();
244
                    popValue();
245
                    popValue();
246
                    popValue();
247
                    break;
248
 
249
                case DUP:
250
                    pushValue(peekValue());
251
                    break;
252
 
253
                case DUP_X1:
254
                // TODO optimize this
255
                {
256
                    Object o1 = popValue();
257
                    Object o2 = popValue();
258
                    pushValue(o1);
259
                    pushValue(o2);
260
                    pushValue(o1);
261
                }
262
                    break;
263
 
264
                case DUP_X2:
265
                // TODO optimize this
266
                {
267
                    Object o1 = popValue();
268
                    Object o2 = popValue();
269
                    Object o3 = popValue();
270
                    pushValue(o1);
271
                    pushValue(o3);
272
                    pushValue(o2);
273
                    pushValue(o1);
274
                }
275
                    break;
276
 
277
                case DUP2:
278
                // TODO optimize this
279
                {
280
                    Object o1 = popValue();
281
                    Object o2 = popValue();
282
                    pushValue(o2);
283
                    pushValue(o1);
284
                    pushValue(o2);
285
                    pushValue(o1);
286
                }
287
                    break;
288
 
289
                case DUP2_X1:
290
                // TODO optimize this
291
                {
292
                    Object o1 = popValue();
293
                    Object o2 = popValue();
294
                    Object o3 = popValue();
295
                    pushValue(o2);
296
                    pushValue(o1);
297
                    pushValue(o3);
298
                    pushValue(o2);
299
                    pushValue(o1);
300
                }
301
                    break;
302
 
303
                case DUP2_X2:
304
                // TODO optimize this
305
                {
306
                    Object o1 = popValue();
307
                    Object o2 = popValue();
308
                    Object o3 = popValue();
309
                    Object o4 = popValue();
310
                    pushValue(o2);
311
                    pushValue(o1);
312
                    pushValue(o4);
313
                    pushValue(o3);
314
                    pushValue(o2);
315
                    pushValue(o1);
316
                }
317
                    break;
318
 
319
                case SWAP: {
320
                    Object o1 = popValue();
321
                    Object o2 = popValue();
322
                    pushValue(o1);
323
                    pushValue(o2);
324
                }
325
                    break;
326
            }
327
        } else {
328
            switch (opcode) {
329
                case RETURN:
330
                case IRETURN:
331
                case FRETURN:
332
                case ARETURN:
333
                case LRETURN:
334
                case DRETURN:
335
                case ATHROW:
336
                    onMethodExit(opcode);
337
                    break;
338
            }
339
        }
340
        mv.visitInsn(opcode);
341
    }
342
 
343
    public void visitVarInsn(int opcode, int var) {
344
        super.visitVarInsn(opcode, var);
345
 
346
        if (constructor) {
347
            switch (opcode) {
348
                case ILOAD:
349
                case FLOAD:
350
                    pushValue(OTHER);
351
                    break;
352
                case LLOAD:
353
                case DLOAD:
354
                    pushValue(OTHER);
355
                    pushValue(OTHER);
356
                    break;
357
                case ALOAD:
358
                    pushValue(var == 0 ? THIS : OTHER);
359
                    break;
360
                case ASTORE:
361
                case ISTORE:
362
                case FSTORE:
363
                    popValue();
364
                    break;
365
                case LSTORE:
366
                case DSTORE:
367
                    popValue();
368
                    popValue();
369
                    break;
370
            }
371
        }
372
    }
373
 
374
    public void visitFieldInsn(
375
        int opcode,
376
        String owner,
377
        String name,
378
        String desc)
379
    {
380
        mv.visitFieldInsn(opcode, owner, name, desc);
381
 
382
        if (constructor) {
383
            char c = desc.charAt(0);
384
            boolean longOrDouble = c == 'J' || c == 'D';
385
            switch (opcode) {
386
                case GETSTATIC:
387
                    pushValue(OTHER);
388
                    if (longOrDouble) {
389
                        pushValue(OTHER);
390
                    }
391
                    break;
392
                case PUTSTATIC:
393
                    popValue();
394
                    if(longOrDouble) {
395
                        popValue();
396
                    }
397
                    break;
398
                case PUTFIELD:
399
                    popValue();
400
                    if(longOrDouble) {
401
                        popValue();
402
                        popValue();
403
                    }
404
                    break;
405
                // case GETFIELD:
406
                default:
407
                    if (longOrDouble) {
408
                        pushValue(OTHER);
409
                    }
410
            }
411
        }
412
    }
413
 
414
    public void visitIntInsn(int opcode, int operand) {
415
        mv.visitIntInsn(opcode, operand);
416
 
417
        if (constructor) {
418
            switch (opcode) {
419
                case BIPUSH:
420
                case SIPUSH:
421
                    pushValue(OTHER);
422
            }
423
        }
424
    }
425
 
426
    public void visitLdcInsn(Object cst) {
427
        mv.visitLdcInsn(cst);
428
 
429
        if (constructor) {
430
            pushValue(OTHER);
431
            if (cst instanceof Double || cst instanceof Long) {
432
                pushValue(OTHER);
433
            }
434
        }
435
    }
436
 
437
    public void visitMultiANewArrayInsn(String desc, int dims) {
438
        mv.visitMultiANewArrayInsn(desc, dims);
439
 
440
        if (constructor) {
441
            for (int i = 0; i < dims; i++) {
442
                popValue();
443
            }
444
            pushValue(OTHER);
445
        }
446
    }
447
 
448
    public void visitTypeInsn(int opcode, String name) {
449
        mv.visitTypeInsn(opcode, name);
450
 
451
        // ANEWARRAY, CHECKCAST or INSTANCEOF don't change stack
452
        if (constructor && opcode == NEW) {
453
            pushValue(OTHER);
454
        }
455
    }
456
 
457
    public void visitMethodInsn(
458
        int opcode,
459
        String owner,
460
        String name,
461
        String desc)
462
    {
463
        mv.visitMethodInsn(opcode, owner, name, desc);
464
 
465
        if (constructor) {
466
            Type[] types = Type.getArgumentTypes(desc);
467
            for (int i = 0; i < types.length; i++) {
468
                popValue();
469
                if (types[i].getSize() == 2) {
470
                    popValue();
471
                }
472
            }
473
            switch (opcode) {
474
                // case INVOKESTATIC:
475
                // break;
476
 
477
                case INVOKEINTERFACE:
478
                case INVOKEVIRTUAL:
479
                    popValue(); // objectref
480
                    break;
481
 
482
                case INVOKESPECIAL:
483
                    Object type = popValue(); // objectref
484
                    if (type == THIS && !superInitialized) {
485
                        onMethodEnter();
486
                        superInitialized = true;
487
                        // once super has been initialized it is no longer
488
                        // necessary to keep track of stack state
489
                        constructor = false;
490
                    }
491
                    break;
492
            }
493
 
494
            Type returnType = Type.getReturnType(desc);
495
            if (returnType != Type.VOID_TYPE) {
496
                pushValue(OTHER);
497
                if (returnType.getSize() == 2) {
498
                    pushValue(OTHER);
499
                }
500
            }
501
        }
502
    }
503
 
504
    public void visitJumpInsn(int opcode, Label label) {
505
        mv.visitJumpInsn(opcode, label);
506
 
507
        if (constructor) {
508
            switch (opcode) {
509
                case IFEQ:
510
                case IFNE:
511
                case IFLT:
512
                case IFGE:
513
                case IFGT:
514
                case IFLE:
515
                case IFNULL:
516
                case IFNONNULL:
517
                    popValue();
518
                    break;
519
 
520
                case IF_ICMPEQ:
521
                case IF_ICMPNE:
522
                case IF_ICMPLT:
523
                case IF_ICMPGE:
524
                case IF_ICMPGT:
525
                case IF_ICMPLE:
526
                case IF_ACMPEQ:
527
                case IF_ACMPNE:
528
                    popValue();
529
                    popValue();
530
                    break;
531
 
532
                case JSR:
533
                    pushValue(OTHER);
534
                    break;
535
            }
536
            addBranch(label);
537
        }
538
    }
539
 
540
    public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
541
        mv.visitLookupSwitchInsn(dflt, keys, labels);
542
 
543
        if (constructor) {
544
            popValue();
545
            addBranches(dflt, labels);
546
        }
547
    }
548
 
549
    public void visitTableSwitchInsn(
550
        int min,
551
        int max,
552
        Label dflt,
553
        Label[] labels)
554
    {
555
        mv.visitTableSwitchInsn(min, max, dflt, labels);
556
 
557
        if (constructor) {
558
            popValue();
559
            addBranches(dflt, labels);
560
        }
561
    }
562
 
563
    private void addBranches(Label dflt, Label[] labels) {
564
        addBranch(dflt);
565
        for (int i = 0; i < labels.length; i++) {
566
            addBranch(labels[i]);
567
        }
568
    }
569
 
570
    private void addBranch(Label label) {
571
        if (branches.containsKey(label)) {
572
            return;
573
        }
574
        ArrayList frame = new ArrayList();
575
        frame.addAll(stackFrame);
576
        branches.put(label, frame);
577
    }
578
 
579
    private Object popValue() {
580
        return stackFrame.remove(stackFrame.size()-1);
581
    }
582
 
583
    private Object peekValue() {
584
        return stackFrame.get(stackFrame.size()-1);
585
    }
586
 
587
    private void pushValue(Object o) {
588
        stackFrame.add(o);
589
    }
590
 
591
    /**
592
     * Called at the beginning of the method or after super
593
     * class class call in the constructor.
594
     * <br><br>
595
     *
596
     * <i>Custom code can use or change all the local variables,
597
     * but should not change state of the stack.</i>
598
     */
599
    protected abstract void onMethodEnter();
600
 
601
    /**
602
     * Called before explicit exit from the method using either
603
     * return or throw. Top element on the stack contains the
604
     * return value or exception instance. For example:
605
     *
606
     * <pre>
607
     *   public void onMethodExit(int opcode) {
608
     *     if(opcode==RETURN) {
609
     *         visitInsn(ACONST_NULL);
610
     *     } else if(opcode==ARETURN || opcode==ATHROW) {
611
     *         dup();
612
     *     } else {
613
     *         if(opcode==LRETURN || opcode==DRETURN) {
614
     *             dup2();
615
     *         } else {
616
     *             dup();
617
     *         }
618
     *         box(Type.getReturnType(this.methodDesc));
619
     *     }
620
     *     visitIntInsn(SIPUSH, opcode);
621
     *     visitMethodInsn(INVOKESTATIC, owner, "onExit", "(Ljava/lang/Object;I)V");
622
     *   }
623
     *
624
     *   // an actual call back method
625
     *   public static void onExit(int opcode, Object param) {
626
     *     ...
627
     * </pre>
628
     *
629
     * <br><br>
630
     *
631
     * <i>Custom code can use or change all the local variables,
632
     * but should not change state of the stack.</i>
633
     *
634
     * @param opcode one of the RETURN, IRETURN, FRETURN,
635
     *   ARETURN, LRETURN, DRETURN or ATHROW
636
     *
637
     */
638
    protected abstract void onMethodExit(int opcode);
639
 
640
    // TODO onException, onMethodCall
641
 
642
}

powered by: WebSVN 2.1.0

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