From 2a7af94c7fd1e595ddfeba680ea98ae53d8dfe50 Mon Sep 17 00:00:00 2001 From: kkhan Date: Sun, 24 Dec 2006 13:47:46 +0000 Subject: [PATCH] Add ability to replace xASTORE and xALOAD calls with invokevirtual git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@338 30ef5769-5b8d-40dd-aea6-55b5d6557bb3 --- src/main/javassist/CodeConverter.java | 9 +- .../convert/TransformAccessArrayField.java | 349 ++++++++++++++++++ 2 files changed, 356 insertions(+), 2 deletions(-) create mode 100644 src/main/javassist/convert/TransformAccessArrayField.java diff --git a/src/main/javassist/CodeConverter.java b/src/main/javassist/CodeConverter.java index d9a18453..77696894 100644 --- a/src/main/javassist/CodeConverter.java +++ b/src/main/javassist/CodeConverter.java @@ -17,6 +17,7 @@ package javassist; import javassist.bytecode.*; import javassist.convert.*; +import javassist.convert.TransformAccessArrayField.MethodNames; /** * Simple translator of method bodies @@ -202,6 +203,11 @@ public class CodeConverter { calledMethod); } + public void replaceArrayAccess(CtClass calledClass, MethodNames names) throws NotFoundException + { + transformers = new TransformAccessArrayField(transformers, calledClass.getName(), names); + } + /** * Modify method invocations in a method body so that a different * method will be invoked. @@ -365,8 +371,7 @@ public class CodeConverter { void doit(CtClass clazz, MethodInfo minfo, ConstPool cp) throws CannotCompileException { - Transformer t; - + Transformer t; CodeAttribute codeAttr = minfo.getCodeAttribute(); if (codeAttr == null || transformers == null) return; diff --git a/src/main/javassist/convert/TransformAccessArrayField.java b/src/main/javassist/convert/TransformAccessArrayField.java new file mode 100644 index 00000000..56ab5a70 --- /dev/null +++ b/src/main/javassist/convert/TransformAccessArrayField.java @@ -0,0 +1,349 @@ +/* + * Javassist, a Java-bytecode translator toolkit. + * Copyright (C) 1999-2006 Shigeru Chiba. All Rights Reserved. + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. Alternatively, the contents of this file may be used under + * the terms of the GNU Lesser General Public License Version 2.1 or later. + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + */ +package javassist.convert; + + +import javassist.CtClass; +import javassist.NotFoundException; +import javassist.bytecode.BadBytecode; +import javassist.bytecode.CodeIterator; +import javassist.bytecode.ConstPool; + +/** + * + * @author Kabir Khan + * @version $Revision: 1.1 $ + */ +public class TransformAccessArrayField extends Transformer +{ +// CtClass componentType; + + String methodClassname; + MethodNames names; + + public TransformAccessArrayField(Transformer next, String methodClassname, MethodNames names) throws NotFoundException + { + super(next); + this.methodClassname = methodClassname; + this.names = names; + } + + public int transform(CtClass tclazz, int pos, CodeIterator iterator, ConstPool cp) throws BadBytecode + { + int c = iterator.byteAt(pos); + + if (c == AALOAD || c == BALOAD || c == CALOAD || c == DALOAD || c == FALOAD || c == IALOAD || c == LALOAD || c == SALOAD) + { + replace(cp, iterator, pos, c, getLoadReplacementSignature(c)); + } + else if (c == AASTORE || c == BASTORE || c == CASTORE || c == DASTORE || c == FASTORE || c == IASTORE || c == LASTORE || c == SASTORE) + { + replace(cp, iterator, pos, c, getStoreReplacementSignature(c)); + } + + return pos; + } + + private void replace(ConstPool cp, CodeIterator iterator, int pos, int opcode, String signature) throws BadBytecode + { + String methodName = getMethodName(opcode); + if (methodName != null) + { + iterator.insertGap(2); + int mi = cp.addClassInfo(methodClassname); + int methodref = cp.addMethodrefInfo(mi, methodName, signature); + iterator.writeByte(INVOKESTATIC, pos); + iterator.write16bit(methodref, pos + 1); + } + } + + private String getMethodName(int opcode) + { + String methodName = null; + switch(opcode) + { + case AALOAD: + methodName = names.objectRead(); + break; + case BALOAD: + methodName = names.byteOrBooleanRead(); + break; + case CALOAD: + methodName = names.charRead(); + break; + case DALOAD: + methodName = names.doubleRead(); + break; + case FALOAD: + methodName = names.floatRead(); + break; + case IALOAD: + methodName = names.intRead(); + break; + case SALOAD: + methodName = names.shortRead(); + break; + case LALOAD: + methodName = names.longRead(); + break; + case AASTORE: + methodName = names.objectWrite(); + break; + case BASTORE: + methodName = names.byteOrBooleanWrite(); + break; + case CASTORE: + methodName = names.charWrite(); + break; + case DASTORE: + methodName = names.doubleWrite(); + break; + case FASTORE: + methodName = names.floatWrite(); + break; + case IASTORE: + methodName = names.intWrite(); + break; + case SASTORE: + methodName = names.shortWrite(); + break; + case LASTORE: + methodName = names.longWrite(); + break; + } + + if (methodName.equals("")) + { + methodName = null; + } + return methodName; + } + + private String getLoadReplacementSignature(int opcode) throws BadBytecode + { + switch(opcode) + { + case AALOAD: + return "(Ljava/lang/Object;I)Ljava/lang/Object;"; + case BALOAD: + return "(Ljava/lang/Object;I)B"; + case CALOAD: + return "(Ljava/lang/Object;I)C"; + case DALOAD: + return "(Ljava/lang/Object;I)D"; + case FALOAD: + return "(Ljava/lang/Object;I)F"; + case IALOAD: + return "(Ljava/lang/Object;I)I"; + case SALOAD: + return "(Ljava/lang/Object;I)S"; + case LALOAD: + return "(Ljava/lang/Object;I)J"; + } + + throw new BadBytecode(opcode); + } + + private String getStoreReplacementSignature(int opcode) throws BadBytecode + { + switch(opcode) + { + case AASTORE: + return "(Ljava/lang/Object;ILjava/lang/Object;)V"; + case BASTORE: + return "(Ljava/lang/Object;IB)V"; + case CASTORE: + return "(Ljava/lang/Object;IC)V"; + case DASTORE: + return "(Ljava/lang/Object;ID)V"; + case FASTORE: + return "(Ljava/lang/Object;IF)V"; + case IASTORE: + return "(Ljava/lang/Object;II)V"; + case SASTORE: + return "(Ljava/lang/Object;IS)V"; + case LASTORE: + return "(Ljava/lang/Object;IJ)V"; + } + throw new BadBytecode(opcode); + } + + public interface MethodNames + { + /** + * Give the name of a static method with the signature (Ljava/lang/Object;I)Ljava/lang/Object; + */ + String objectRead(); + + /** + * Give the name of a static method with the signature (Ljava/lang/Object;I)B" + */ + String byteOrBooleanRead(); + + /** + * Give the name of a static method with the signature (Ljava/lang/Object;I)C + */ + String charRead(); + + /** + * Give the name of a static method with the signature (Ljava/lang/Object;I)D + */ + String doubleRead(); + + /** + * Give the name of a static method with the signature (Ljava/lang/Object;I)F + */ + String floatRead(); + + /** + * Give the name of a static method with the signature (Ljava/lang/Object;I)I + */ + String intRead(); + + /** + * Give the name of a static method with the signature (Ljava/lang/Object;I)J + */ + String longRead(); + + /** + * Give the name of a static method with the signature (Ljava/lang/Object;I)S + */ + String shortRead(); + + /** + * Give the name of a static method with the signature (Ljava/lang/Object;ILjava/lang/Object;)V + */ + String objectWrite(); + + /** + * Give the name of a static method with the signature (Ljava/lang/Object;IB)V + */ + String byteOrBooleanWrite(); + + /** + * Give the name of a static method with the signature (Ljava/lang/Object;IC)V + */ + String charWrite(); + + /** + * Give the name of a static method with the signature (Ljava/lang/Object;ID)V + */ + String doubleWrite(); + + /** + * Give the name of a static method with the signature (Ljava/lang/Object;IF)V + */ + String floatWrite(); + + /** + * Give the name of a static method with the signature (Ljava/lang/Object;II)V + */ + String intWrite(); + + /** + * Give the name of a static method with the signature (Ljava/lang/Object;IJ)V + */ + String longWrite(); + + /** + * Give the name of a static method with the signature (Ljava/lang/Object;IS)V + */ + String shortWrite(); + } + + public static class DefaultMethodNames implements MethodNames + { + public String byteOrBooleanRead() + { + return "arrayReadByteOrBoolean"; + } + + public String byteOrBooleanWrite() + { + return "arrayWriteByteOrBoolean"; + } + + public String charRead() + { + return "arrayReadChar"; + } + + public String charWrite() + { + return "arrayWriteChar"; + } + + public String doubleRead() + { + return "arrayReadDouble"; + } + + public String doubleWrite() + { + return "arrayWriteDouble"; + } + + public String floatRead() + { + return "arrayReadFloat"; + } + + public String floatWrite() + { + return "arrayWriteFloat"; + } + + public String intRead() + { + return "arrayReadInt"; + } + + public String intWrite() + { + return "arrayWriteInt"; + } + + public String longRead() + { + return "arrayReadLong"; + } + + public String longWrite() + { + return "arrayWriteLong"; + } + + public String objectRead() + { + return "arrayReadObject"; + } + + public String objectWrite() + { + return "arrayWriteObject"; + } + + public String shortRead() + { + return "arrayReadShort"; + } + + public String shortWrite() + { + return "arrayWriteShort"; + } + + } +} -- 2.39.5