/Users/lyon/j4p/src/javassist/convert/TransformBefore.java

1    /* 
2     * Javassist, a Java-bytecode translator toolkit. 
3     * Copyright (C) 1999-2003 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   import javassist.CannotCompileException; 
23    
24   public class TransformBefore extends TransformCall { 
25       protected CtClass[] parameterTypes; 
26       protected int locals; 
27       protected int maxLocals; 
28       protected byte[] saveCode, loadCode; 
29    
30       public TransformBefore(Transformer next, 
31                              CtMethod origMethod, CtMethod beforeMethod) 
32               throws NotFoundException { 
33           super(next, origMethod, beforeMethod); 
34           parameterTypes = origMethod.getParameterTypes(); 
35           locals = 0; 
36           maxLocals = 0; 
37           saveCode = loadCode = null; 
38       } 
39    
40       public void initialize(ConstPool cp, CodeAttribute attr) { 
41           super.initialize(cp, attr); 
42           locals = 0; 
43           maxLocals = attr.getMaxLocals(); 
44           saveCode = loadCode = null; 
45       } 
46    
47       protected int match(int c, int pos, CodeIterator iterator, 
48                           int typedesc, ConstPool cp) throws BadBytecode { 
49           if (newIndex == 0) { 
50               String desc = Descriptor.ofParameters(parameterTypes) + 'V'; 
51               desc = Descriptor.insertParameter(classname, desc); 
52               int nt = cp.addNameAndTypeInfo(newMethodname, desc); 
53               int ci = cp.addClassInfo(newClassname); 
54               newIndex = cp.addMethodrefInfo(ci, nt); 
55               constPool = cp; 
56           } 
57    
58           if (saveCode == null) 
59               makeCode(parameterTypes, cp); 
60    
61           return match2(pos, iterator); 
62       } 
63    
64       protected int match2(int pos, CodeIterator iterator) throws BadBytecode { 
65           iterator.move(pos); 
66           iterator.insert(saveCode); 
67           iterator.insert(loadCode); 
68           int p = iterator.insertGap(3); 
69           iterator.writeByte(INVOKESTATIC, p); 
70           iterator.write16bit(newIndex, p + 1); 
71           iterator.insert(loadCode); 
72           return iterator.next(); 
73       } 
74    
75       public int extraLocals() { 
76           return locals; 
77       } 
78    
79       protected void makeCode(CtClass[] paramTypes, ConstPool cp) { 
80           Bytecode save = new Bytecode(cp, 0, 0); 
81           Bytecode load = new Bytecode(cp, 0, 0); 
82    
83           int var = maxLocals; 
84           int len = (paramTypes == null) ? 0 : paramTypes.length; 
85           load.addAload(var); 
86           makeCode2(save, load, 0, len, paramTypes, var + 1); 
87           save.addAstore(var); 
88    
89           saveCode = save.get(); 
90           loadCode = load.get(); 
91       } 
92    
93       private void makeCode2(Bytecode save, Bytecode load, 
94                              int i, int n, CtClass[] paramTypes, int var) { 
95           if (i < n) { 
96               int size = load.addLoad(var, paramTypes[i]); 
97               makeCode2(save, load, i + 1, n, paramTypes, var + size); 
98               save.addStore(var, paramTypes[i]); 
99           } else 
100              locals = var - maxLocals; 
101      } 
102  } 
103