KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > cglib > core > LocalVariablesSorter


1 /***
2  * ASM: a very small and fast Java bytecode manipulation framework
3  * Copyright (c) 2000-2005 INRIA, France Telecom
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  * 3. Neither the name of the copyright holders nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28  * THE POSSIBILITY OF SUCH DAMAGE.
29  */

30 package net.sf.cglib.core;
31
32 import org.objectweb.asm.Label;
33 import org.objectweb.asm.MethodAdapter;
34 import org.objectweb.asm.MethodVisitor;
35 import org.objectweb.asm.Opcodes;
36 import org.objectweb.asm.Type;
37
38 /**
39  * A {@link MethodAdapter} that renumbers local variables in their order of
40  * appearance. This adapter allows one to easily add new local variables to a
41  * method.
42  *
43  * @author Chris Nokleberg
44  * @author Eric Bruneton
45  */

46 public class LocalVariablesSorter extends MethodAdapter {
47
48     /**
49      * Mapping from old to new local variable indexes. A local variable at index
50      * i of size 1 is remapped to 'mapping[2*i]', while a local variable at
51      * index i of size 2 is remapped to 'mapping[2*i+1]'.
52      */

53     private static class State
54     {
55         int[] mapping = new int[40];
56         int nextLocal;
57     }
58
59     protected final int firstLocal;
60     private final State state;
61
62     public LocalVariablesSorter(
63         final int access,
64         final String JavaDoc desc,
65         final MethodVisitor mv)
66     {
67         super(mv);
68         state = new State();
69         Type[] args = Type.getArgumentTypes(desc);
70         state.nextLocal = ((Opcodes.ACC_STATIC & access) != 0) ? 0 : 1;
71         for (int i = 0; i < args.length; i++) {
72             state.nextLocal += args[i].getSize();
73         }
74         firstLocal = state.nextLocal;
75     }
76
77     public LocalVariablesSorter(LocalVariablesSorter lvs) {
78         super(lvs.mv);
79         state = lvs.state;
80         firstLocal = lvs.firstLocal;
81     }
82
83     public void visitVarInsn(final int opcode, final int var) {
84         int size;
85         switch (opcode) {
86             case Opcodes.LLOAD:
87             case Opcodes.LSTORE:
88             case Opcodes.DLOAD:
89             case Opcodes.DSTORE:
90                 size = 2;
91                 break;
92             default:
93                 size = 1;
94         }
95         mv.visitVarInsn(opcode, remap(var, size));
96     }
97
98     public void visitIincInsn(final int var, final int increment) {
99         mv.visitIincInsn(remap(var, 1), increment);
100     }
101
102     public void visitMaxs(final int maxStack, final int maxLocals) {
103         mv.visitMaxs(maxStack, state.nextLocal);
104     }
105
106     public void visitLocalVariable(
107         final String JavaDoc name,
108         final String JavaDoc desc,
109         final String JavaDoc signature,
110         final Label start,
111         final Label end,
112         final int index)
113     {
114         mv.visitLocalVariable(name, desc, signature, start, end, remap(index));
115     }
116
117     // -------------
118

119     protected int newLocal(final int size) {
120         int var = state.nextLocal;
121         state.nextLocal += size;
122         return var;
123     }
124
125     private int remap(final int var, final int size) {
126         if (var < firstLocal) {
127             return var;
128         }
129         int key = 2 * var + size - 1;
130         int length = state.mapping.length;
131         if (key >= length) {
132             int[] newMapping = new int[Math.max(2 * length, key + 1)];
133             System.arraycopy(state.mapping, 0, newMapping, 0, length);
134             state.mapping = newMapping;
135         }
136         int value = state.mapping[key];
137         if (value == 0) {
138             value = state.nextLocal + 1;
139             state.mapping[key] = value;
140             state.nextLocal += size;
141         }
142         return value - 1;
143     }
144
145     private int remap(final int var) {
146         if (var < firstLocal) {
147             return var;
148         }
149         int key = 2 * var;
150         int value = key < state.mapping.length ? state.mapping[key] : 0;
151         if (value == 0) {
152             value = key + 1 < state.mapping.length ? state.mapping[key + 1] : 0;
153         }
154         if (value == 0) {
155             throw new IllegalStateException JavaDoc("Unknown local variable " + var);
156         }
157         return value - 1;
158     }
159 }
160
Popular Tags