Home | History | Annotate | Download | only in convert
      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 
     16 package javassist.convert;
     17 
     18 import javassist.CtClass;
     19 import javassist.CtMethod;
     20 import javassist.NotFoundException;
     21 import javassist.bytecode.*;
     22 
     23 public 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