001: // Copyright (c) 2003-2007, Jodd Team (jodd.sf.net). All Rights Reserved.
002:
003: package jodd.proxetta;
004:
005: import org.objectweb.asm.MethodAdapter;
006: import org.objectweb.asm.MethodVisitor;
007: import org.objectweb.asm.Label;
008: import static org.objectweb.asm.Opcodes.*;
009:
010: /**
011: * Method adapter that remebers the previous opcode of 'insn' and 'intInsn' instructions.
012: * Used to detect single int argument value when calling a method.
013: */
014: abstract class HistoryMethodAdapter extends MethodAdapter {
015:
016: protected HistoryMethodAdapter(MethodVisitor methodVisitor) {
017: super (methodVisitor);
018: }
019:
020: // ---------------------------------------------------------------- history
021:
022: protected int opcode;
023: protected int operand;
024: protected boolean isPrevious; // true only if previous opcode is of the correct type
025: protected boolean traceNext; // true only to trace very next opcode
026:
027: // ---------------------------------------------------------------- get index
028:
029: /**
030: * Returns argument index from the history.
031: * <b>Must</b> POP value from the stack after the execution.
032: */
033: protected int getArgumentIndex() {
034: if (isPrevious == false) {
035: throw new ProxettaException(
036: "Unexpected previous instruction type used for setting argument index.");
037: }
038: int argIndex;
039: switch (opcode) {
040: case ICONST_0:
041: argIndex = 0;
042: break;
043: case ICONST_1:
044: argIndex = 1;
045: break;
046: case ICONST_2:
047: argIndex = 2;
048: break;
049: case ICONST_3:
050: argIndex = 3;
051: break;
052: case ICONST_4:
053: argIndex = 4;
054: break;
055: case ICONST_5:
056: argIndex = 5;
057: break;
058: case BIPUSH:
059: case SIPUSH:
060: argIndex = operand;
061: break;
062: default:
063: throw new ProxettaException(
064: "Unexpected previous instruction used for setting argument index.");
065: }
066: return argIndex;
067: }
068:
069: // ---------------------------------------------------------------- visitors
070:
071: @Override
072: public void visitInsn(int opcode) {
073: this .opcode = opcode;
074: isPrevious = true;
075: traceNext = false;
076: super .visitInsn(opcode);
077: }
078:
079: @Override
080: public void visitIntInsn(int opcode, int operand) {
081: this .opcode = opcode;
082: this .operand = operand;
083: isPrevious = true;
084: traceNext = false;
085: super .visitIntInsn(opcode, operand);
086: }
087:
088: @Override
089: public void visitVarInsn(int i, int i1) {
090: isPrevious = false;
091: traceNext = false;
092: super .visitVarInsn(i, i1);
093: }
094:
095: @Override
096: public void visitTypeInsn(int i, String string) {
097: isPrevious = false;
098: traceNext = false;
099: super .visitTypeInsn(i, string);
100: }
101:
102: @Override
103: public void visitFieldInsn(int i, String string, String string1,
104: String string2) {
105: isPrevious = false;
106: traceNext = false;
107: super .visitFieldInsn(i, string, string1, string2);
108: }
109:
110: @Override
111: public void visitMethodInsn(int i, String string, String string1,
112: String string2) {
113: isPrevious = false;
114: traceNext = false;
115: super .visitMethodInsn(i, string, string1, string2);
116: }
117:
118: @Override
119: public void visitJumpInsn(int i, Label label) {
120: isPrevious = false;
121: traceNext = false;
122: super .visitJumpInsn(i, label);
123: }
124:
125: @Override
126: public void visitLdcInsn(Object object) {
127: isPrevious = false;
128: traceNext = false;
129: super .visitLdcInsn(object);
130: }
131:
132: @Override
133: public void visitIincInsn(int i, int i1) {
134: isPrevious = false;
135: traceNext = false;
136: super .visitIincInsn(i, i1);
137: }
138:
139: @Override
140: public void visitTableSwitchInsn(int i, int i1, Label label,
141: Label[] labels) {
142: isPrevious = false;
143: traceNext = false;
144: super .visitTableSwitchInsn(i, i1, label, labels);
145: }
146:
147: @Override
148: public void visitLookupSwitchInsn(Label label, int[] ints,
149: Label[] labels) {
150: isPrevious = false;
151: traceNext = false;
152: super .visitLookupSwitchInsn(label, ints, labels);
153: }
154:
155: @Override
156: public void visitMultiANewArrayInsn(String string, int i) {
157: isPrevious = false;
158: traceNext = false;
159: super.visitMultiANewArrayInsn(string, i);
160: }
161:
162: }
|