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