KickJava   Java API By Example, From Geeks To Geeks.

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


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

5 package com.tc.object.bytecode;
6
7 import com.tc.asm.ClassAdapter;
8 import com.tc.asm.ClassVisitor;
9 import com.tc.asm.MethodAdapter;
10 import com.tc.asm.MethodVisitor;
11 import com.tc.asm.Opcodes;
12 import com.tc.object.bytecode.hook.impl.JavaLangArrayHelpers;
13 import com.tc.util.Assert;
14 import com.tc.util.runtime.Vm;
15 import com.tc.util.runtime.Vm.Version;
16
17 public class JavaLangStringAdapter extends ClassAdapter implements Opcodes {
18
19   private final Version vmVersion;
20   private final boolean portableStringBuffer;
21
22   public JavaLangStringAdapter(ClassVisitor cv, Version vmVersion, boolean portableStringBuffer) {
23     super(cv);
24     this.vmVersion = vmVersion;
25     this.portableStringBuffer = portableStringBuffer;
26   }
27
28   public MethodVisitor visitMethod(int access, String JavaDoc name, String JavaDoc desc, String JavaDoc signature, String JavaDoc[] exceptions) {
29     MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
30     if ("getBytes".equals(name) && "(II[BI)V".equals(desc)) {
31       return rewriteGetBytes(mv);
32     } else if ("<init>".equals(name) && "(Ljava/lang/StringBuffer;)V".equals(desc)) {
33       if (vmVersion.isJDK14() && portableStringBuffer) { return rewriteStringBufferConstructor(mv); }
34     } else if ("getChars".equals(name) && "(II[CI)V".equals(desc)) {
35       // make formatter sane
36
return new GetCharsAdapter(mv);
37     } else if ("getChars".equals(name) && "([CI)V".equals(desc)) {
38       // This method is in the 1.5 Sun impl of String
39
return new GetCharsAdapter(mv);
40     }
41
42     return new RewriteGetCharsCallsAdapter(mv);
43   }
44
45   public void visitEnd() {
46     addFastGetChars();
47     super.visitEnd();
48   }
49
50   private void addFastGetChars() {
51     // Called by the unmanaged paths of StringBuffer, StringBuilder, etc. Also called it strategic places where the
52
// target char[] is known (or assumed) to be non-shared
53
MethodVisitor mv = super.visitMethod(ACC_SYNTHETIC | ACC_PUBLIC, "getCharsFast", "(II[CI)V", null, null);
54     mv.visitCode();
55     mv.visitVarInsn(ALOAD, 0);
56     mv.visitFieldInsn(GETFIELD, "java/lang/String", "value", "[C");
57     mv.visitVarInsn(ALOAD, 0);
58     mv.visitFieldInsn(GETFIELD, "java/lang/String", "offset", "I");
59     mv.visitVarInsn(ILOAD, 1);
60     mv.visitInsn(IADD);
61     mv.visitVarInsn(ALOAD, 3);
62     mv.visitVarInsn(ILOAD, 4);
63     mv.visitVarInsn(ILOAD, 2);
64     mv.visitVarInsn(ILOAD, 1);
65     mv.visitInsn(ISUB);
66     mv.visitMethodInsn(INVOKESTATIC, "java/lang/System", "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V");
67     mv.visitInsn(RETURN);
68     mv.visitMaxs(0, 0);
69     mv.visitEnd();
70
71     // Called from AbstractStringBuilder.insert|repace()
72
mv = super.visitMethod(ACC_SYNTHETIC, "getCharsFast", "([CI)V", null, null);
73     mv.visitCode();
74     mv.visitVarInsn(ALOAD, 0);
75     mv.visitFieldInsn(GETFIELD, "java/lang/String", "value", "[C");
76     mv.visitVarInsn(ALOAD, 0);
77     mv.visitFieldInsn(GETFIELD, "java/lang/String", "offset", "I");
78     mv.visitVarInsn(ALOAD, 1);
79     mv.visitVarInsn(ILOAD, 2);
80     mv.visitVarInsn(ALOAD, 0);
81     mv.visitFieldInsn(GETFIELD, "java/lang/String", "count", "I");
82     mv.visitMethodInsn(INVOKESTATIC, "java/lang/System", "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V");
83     mv.visitInsn(RETURN);
84     mv.visitMaxs(0, 0);
85     mv.visitEnd();
86   }
87
88   private MethodVisitor rewriteStringBufferConstructor(MethodVisitor mv) {
89     // move the sync into StringBuffer.toString() where it belongs
90
Assert.assertTrue(Vm.isJDK14());
91     mv.visitCode();
92     mv.visitVarInsn(ALOAD, 0);
93     mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
94     mv.visitVarInsn(ALOAD, 1);
95     mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuffer", "toString", "()Ljava/lang/String;");
96     mv.visitVarInsn(ASTORE, 2);
97     mv.visitVarInsn(ALOAD, 0);
98     mv.visitVarInsn(ALOAD, 2);
99     mv.visitFieldInsn(GETFIELD, "java/lang/String", "value", "[C");
100     mv.visitFieldInsn(PUTFIELD, "java/lang/String", "value", "[C");
101     mv.visitVarInsn(ALOAD, 0);
102     mv.visitVarInsn(ALOAD, 2);
103     mv.visitFieldInsn(GETFIELD, "java/lang/String", "count", "I");
104     mv.visitFieldInsn(PUTFIELD, "java/lang/String", "count", "I");
105     mv.visitVarInsn(ALOAD, 0);
106     mv.visitVarInsn(ALOAD, 2);
107     mv.visitFieldInsn(GETFIELD, "java/lang/String", "offset", "I");
108     mv.visitFieldInsn(PUTFIELD, "java/lang/String", "offset", "I");
109     mv.visitInsn(RETURN);
110     mv.visitMaxs(0, 0);
111     return null;
112   }
113
114   private MethodVisitor rewriteGetBytes(MethodVisitor mv) {
115     mv.visitCode();
116     mv.visitVarInsn(ILOAD, 1);
117     mv.visitVarInsn(ILOAD, 2);
118     mv.visitVarInsn(ALOAD, 3);
119     mv.visitVarInsn(ILOAD, 4);
120     mv.visitVarInsn(ALOAD, 0);
121     mv.visitFieldInsn(GETFIELD, "java/lang/String", "count", "I");
122     mv.visitVarInsn(ALOAD, 0);
123     mv.visitFieldInsn(GETFIELD, "java/lang/String", "offset", "I");
124     mv.visitVarInsn(ALOAD, 0);
125     mv.visitFieldInsn(GETFIELD, "java/lang/String", "value", "[C");
126     mv.visitMethodInsn(INVOKESTATIC, JavaLangArrayHelpers.CLASS, "javaLangStringGetBytes", "(II[BIII[C)V");
127     mv.visitInsn(RETURN);
128     mv.visitMaxs(0, 0);
129     mv.visitEnd();
130     return null;
131   }
132
133   private static class RewriteGetCharsCallsAdapter extends MethodAdapter {
134
135     public RewriteGetCharsCallsAdapter(MethodVisitor mv) {
136       super(mv);
137     }
138
139     public void visitMethodInsn(int opcode, String JavaDoc owner, String JavaDoc name, String JavaDoc desc) {
140       if ((INVOKEVIRTUAL == opcode) && ("java/lang/String".equals(owner) && "getChars".equals(name))) {
141         super.visitMethodInsn(opcode, owner, "getCharsFast", desc);
142       } else {
143         super.visitMethodInsn(opcode, owner, name, desc);
144       }
145     }
146
147   }
148
149   private static class GetCharsAdapter extends MethodAdapter {
150
151     public GetCharsAdapter(MethodVisitor mv) {
152       super(mv);
153     }
154
155     public void visitMethodInsn(int opcode, String JavaDoc owner, String JavaDoc name, String JavaDoc desc) {
156       if ((opcode == INVOKESTATIC) && "java/lang/System".equals(owner) && "arraycopy".equals(name)) {
157         super.visitMethodInsn(INVOKESTATIC, JavaLangArrayHelpers.CLASS, "charArrayCopy", "([CI[CII)V");
158       } else {
159         super.visitMethodInsn(opcode, owner, name, desc);
160       }
161     }
162
163   }
164
165 }
166
Popular Tags