1/* 2 * Javassist, a Java-bytecode translator toolkit. 3 * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved. 4 * 5 * The contents of this file are subject to the Mozilla Public License Version 6 * 1.1 (the "License"); you may not use this file except in compliance with 7 * the License. Alternatively, the contents of this file may be used under 8 * the terms of the GNU Lesser General Public License Version 2.1 or later. 9 * 10 * Software distributed under the License is distributed on an "AS IS" basis, 11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 12 * for the specific language governing rights and limitations under the 13 * License. 14 */ 15 16package javassist.convert; 17 18import javassist.CtClass; 19import javassist.CtMethod; 20import javassist.NotFoundException; 21import javassist.bytecode.*; 22 23public class TransformBefore extends TransformCall { 24 protected CtClass[] parameterTypes; 25 protected int locals; 26 protected int maxLocals; 27 protected byte[] saveCode, loadCode; 28 29 public TransformBefore(Transformer next, 30 CtMethod origMethod, CtMethod beforeMethod) 31 throws NotFoundException 32 { 33 super(next, origMethod, beforeMethod); 34 35 // override 36 methodDescriptor = origMethod.getMethodInfo2().getDescriptor(); 37 38 parameterTypes = origMethod.getParameterTypes(); 39 locals = 0; 40 maxLocals = 0; 41 saveCode = loadCode = null; 42 } 43 44 public void initialize(ConstPool cp, CodeAttribute attr) { 45 super.initialize(cp, attr); 46 locals = 0; 47 maxLocals = attr.getMaxLocals(); 48 saveCode = loadCode = null; 49 } 50 51 protected int match(int c, int pos, CodeIterator iterator, 52 int typedesc, ConstPool cp) throws BadBytecode 53 { 54 if (newIndex == 0) { 55 String desc = Descriptor.ofParameters(parameterTypes) + 'V'; 56 desc = Descriptor.insertParameter(classname, desc); 57 int nt = cp.addNameAndTypeInfo(newMethodname, desc); 58 int ci = cp.addClassInfo(newClassname); 59 newIndex = cp.addMethodrefInfo(ci, nt); 60 constPool = cp; 61 } 62 63 if (saveCode == null) 64 makeCode(parameterTypes, cp); 65 66 return match2(pos, iterator); 67 } 68 69 protected int match2(int pos, CodeIterator iterator) throws BadBytecode { 70 iterator.move(pos); 71 iterator.insert(saveCode); 72 iterator.insert(loadCode); 73 int p = iterator.insertGap(3); 74 iterator.writeByte(INVOKESTATIC, p); 75 iterator.write16bit(newIndex, p + 1); 76 iterator.insert(loadCode); 77 return iterator.next(); 78 } 79 80 public int extraLocals() { return locals; } 81 82 protected void makeCode(CtClass[] paramTypes, ConstPool cp) { 83 Bytecode save = new Bytecode(cp, 0, 0); 84 Bytecode load = new Bytecode(cp, 0, 0); 85 86 int var = maxLocals; 87 int len = (paramTypes == null) ? 0 : paramTypes.length; 88 load.addAload(var); 89 makeCode2(save, load, 0, len, paramTypes, var + 1); 90 save.addAstore(var); 91 92 saveCode = save.get(); 93 loadCode = load.get(); 94 } 95 96 private void makeCode2(Bytecode save, Bytecode load, 97 int i, int n, CtClass[] paramTypes, int var) 98 { 99 if (i < n) { 100 int size = load.addLoad(var, paramTypes[i]); 101 makeCode2(save, load, i + 1, n, paramTypes, var + size); 102 save.addStore(var, paramTypes[i]); 103 } 104 else 105 locals = var - maxLocals; 106 } 107} 108