1 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 46 public class LocalVariablesSorter extends MethodAdapter { 47 48 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 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 name, 108 final String desc, 109 final String 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 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 ("Unknown local variable " + var); 156 } 157 return value - 1; 158 } 159 } 160 | Popular Tags |