1 16 package net.sf.cglib.core; 17 18 import org.objectweb.asm.*; 19 import java.util.*; 20 21 public class RemappingCodeVisitor extends CodeAdapter { 22 private State state; 23 private IntRef check = new IntRef(); 24 25 private static class State { 26 Map locals = new HashMap(); 27 int firstLocal; 28 int nextLocal; 29 30 State(int access, Type[] args) { 31 nextLocal = ((Constants.ACC_STATIC & access) != 0) ? 0 : 1; 32 for (int i = 0; i < args.length; i++) { 33 nextLocal += args[i].getSize(); 34 } 35 firstLocal = nextLocal; 36 } 37 } 38 39 private static class IntRef { 40 int key; 41 public boolean equals(Object o) { 42 return key == ((IntRef)o).key; 43 } 44 public int hashCode() { 45 return key; 46 } 47 } 48 49 public RemappingCodeVisitor(CodeVisitor v, int access, Type[] args) { 50 super(v); 51 state = new State(access, args); 52 } 53 54 public RemappingCodeVisitor(RemappingCodeVisitor wrap) { 55 super(wrap.cv); 56 this.state = wrap.state; 57 } 58 59 protected int nextLocal(int size) { 60 int var = state.nextLocal; 61 state.nextLocal += size; 62 return var; 63 } 64 65 private int remap(int var, int size) { 66 if (var < state.firstLocal) { 67 return var; 68 } 69 Integer value = remapHelper(var, (size == 0) ? 1 : size); 70 if (value == null) { 71 if (size == 0) { 72 value = remapHelper(var, 2); 73 if (value == null) { 74 throw new IllegalStateException ("Unknown local variable " + var); 75 } 76 } else { 77 IntRef ref = new IntRef(); 78 ref.key = getKey(var, size); 79 state.locals.put(ref, value = new Integer (nextLocal(size))); 80 } 81 } 82 return value.intValue(); 84 } 85 86 private Integer remapHelper(int var, int size) { 87 check.key = getKey(var, size); 88 return (Integer )state.locals.get(check); 89 } 90 91 private int getKey(int var, int size) { 92 return (size == 2) ? ~var : var; 93 } 94 95 public void visitIincInsn(int var, int increment) { 96 cv.visitIincInsn(remap(var, 1), increment); 97 } 98 99 public void visitLocalVariable(String name, String desc, Label start, Label end, int index) { 100 cv.visitLocalVariable(name, desc, start, end, remap(index, 0)); 101 } 102 103 public void visitVarInsn(int opcode, int var) { 104 int size; 105 switch (opcode) { 106 case Constants.LLOAD: 107 case Constants.LSTORE: 108 case Constants.DLOAD: 109 case Constants.DSTORE: 110 size = 2; 111 break; 112 default: 113 size = 1; 114 } 115 cv.visitVarInsn(opcode, remap(var, size)); 116 } 117 118 public void visitMaxs(int maxStack, int maxLocals) { 119 cv.visitMaxs(0, 0); 120 } 121 } 122 123 | Popular Tags |