KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > tc > object > bytecode > AbstractStringBuilderAdapter


1 /*
2  * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
3  */

4 package com.tc.object.bytecode;
5
6 import com.tc.asm.ClassAdapter;
7 import com.tc.asm.ClassVisitor;
8 import com.tc.asm.MethodAdapter;
9 import com.tc.asm.MethodVisitor;
10 import com.tc.asm.Opcodes;
11 import com.tc.object.bytecode.hook.impl.JavaLangArrayHelpers;
12
13 public class AbstractStringBuilderAdapter extends ClassAdapter {
14
15   public AbstractStringBuilderAdapter(ClassVisitor cv) {
16     super(cv);
17   }
18
19   public MethodVisitor visitMethod(int access, String JavaDoc name, String JavaDoc desc, String JavaDoc signature, String JavaDoc[] exceptions) {
20     MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
21     if ((DuplicateMethodAdapter.MANAGED_PREFIX + "append").equals(name)) {
22       if ("(I)Ljava/lang/AbstractStringBuilder;".equals(desc)) {
23         return new AppendAdapter(mv, "I");
24       } else if ("(J)Ljava/lang/AbstractStringBuilder;".equals(desc)) { return new AppendAdapter(mv, "J"); }
25     }
26
27     return mv;
28   }
29
30   private static class AppendAdapter extends MethodAdapter implements Opcodes {
31
32     private final int spaceNeededSlot;
33     private final int countSlot;
34     private boolean hasVisitedOnce = false;
35
36     public AppendAdapter(MethodVisitor mv, String JavaDoc type) {
37       super(mv);
38
39       if (!"J".equals(type) && !"I".equals(type)) { throw new AssertionError JavaDoc("bad type: " + type); }
40
41       this.spaceNeededSlot = type.equals("I") ? 2 : 3;
42       this.countSlot = type.equals("I") ? 3 : 4;
43     }
44
45     public void visitInsn(int opcode) {
46       if (opcode == ARETURN) {
47
48         // This is a hack to fix append(int) and append(long) where the argument is either Integer.MIN_VALUE
49
// or Long.MIN_VALUE. In either of those cases, we do not want to call
50
// JavaLangArrayHelpers.javaLangAbstractStringBuilderAppend.
51
if (!hasVisitedOnce) {
52           hasVisitedOnce = true;
53           super.visitInsn(opcode);
54           return;
55         }
56
57         mv.visitVarInsn(ALOAD, 0);
58         mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/AbstractStringBuilder", ByteCodeUtil.fieldGetterMethod("value"),
59                            "()[C");
60         mv.visitVarInsn(ILOAD, spaceNeededSlot);
61         mv.visitVarInsn(ILOAD, countSlot);
62         mv.visitMethodInsn(INVOKESTATIC, JavaLangArrayHelpers.CLASS, "javaLangAbstractStringBuilderAppend", "([CII)V");
63
64         super.visitInsn(opcode);
65         return;
66       }
67
68       super.visitInsn(opcode);
69     }
70
71   }
72
73 }
74
Popular Tags