1 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 name, String desc, String signature, String [] 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 return new GetCharsAdapter(mv); 37 } else if ("getChars".equals(name) && "([CI)V".equals(desc)) { 38 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 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 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 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 owner, String name, String 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 owner, String name, String 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 |