View Javadoc

1   /*
2    *
3    */
4   package org.softevo.jdynpur.runtime;
5   
6   import org.objectweb.asm.MethodVisitor;
7   import org.objectweb.asm.Opcodes;
8   import org.objectweb.asm.commons.LocalVariablesSorter;
9   
10  public class ArrayTracingVisitor extends LocalVariablesSorter implements Opcodes {
11  
12  	private int temporaryVariableIndex = -1;
13  
14  	public ArrayTracingVisitor(MethodVisitor visitor, int access, String desc) {
15  		super(access, desc, visitor);
16  	}
17  
18  	@Override
19  	public void visitTypeInsn(int opcode, String typeDescription) {
20  		if (opcode == ANEWARRAY) {
21  			super.visitTypeInsn(opcode, typeDescription);
22  			super.visitInsn(DUP);
23  			super.visitMethodInsn(INVOKESTATIC, OnTheFlyInstrumenter.TRACECLASSNAME, "arrayCreated", "(Ljava/lang/Object;)V");
24  		} else {
25  			super.visitTypeInsn(opcode, typeDescription);
26  		}
27  	}
28  
29  	@Override
30  	public void visitIntInsn(int opcode, int operand) {
31  		if (opcode == NEWARRAY) {
32  			super.visitIntInsn(opcode, operand);
33  			super.visitInsn(DUP);
34  			super.visitMethodInsn(INVOKESTATIC, OnTheFlyInstrumenter.TRACECLASSNAME, "arrayCreated", "(Ljava/lang/Object;)V");
35  		} else {
36  			super.visitIntInsn(opcode, operand);
37  		}
38  	}
39  
40  	@Override
41  	public void visitInsn(int opcode) {
42  		int storeOpCode, loadOpCode;
43  
44  		if ((opcode == AASTORE) || (opcode == SASTORE) || (opcode == BASTORE) || (opcode == CASTORE) || (opcode == FASTORE)
45  				|| (opcode == IASTORE)) {
46  			super.visitInsn(DUP2_X1);
47  			super.visitInsn(POP2);
48  			super.visitInsn(DUP_X2);
49  			super
50  					.visitMethodInsn(INVOKESTATIC, OnTheFlyInstrumenter.TRACECLASSNAME, "arrayModified", "(Ljava/lang/Object;)V");
51  			super.visitInsn(opcode);
52  		} else if (opcode == AASTORE) {
53  			//this effectively duplicates the three top operand stack words
54  			super.visitInsn(DUP2_X1);
55  			super.visitInsn(POP2);
56  			super.visitInsn(DUP_X2);
57  			super.visitInsn(DUP2_X1);
58  			super.visitInsn(POP2);
59  			super.visitInsn(DUP_X2);
60  			super.visitInsn(DUP2_X1);
61  			super.visitInsn(POP2);
62  			super.visitInsn(DUP_X2);
63  			super.visitInsn(opcode);
64  			super.visitMethodInsn(INVOKESTATIC, OnTheFlyInstrumenter.TRACECLASSNAME, "objectArrayModified", "(Ljava/lang/Object;ILjava/lang/Object;)V");
65  		} else if ((opcode == LASTORE) || (opcode == DASTORE)) {
66  			if (opcode == LASTORE) {
67  				storeOpCode = LSTORE;
68  				loadOpCode = LLOAD;
69  			} else {
70  				storeOpCode = DSTORE;
71  				loadOpCode = DLOAD;
72  			}
73  			if (temporaryVariableIndex == -1) {
74  				temporaryVariableIndex = newLocal(2);
75  			}
76  			super.visitVarInsn(storeOpCode, temporaryVariableIndex);
77  			super.visitInsn(SWAP);
78  			super.visitInsn(DUP_X1);
79  			super.visitInsn(SWAP);
80  			super.visitVarInsn(loadOpCode, temporaryVariableIndex);
81  			// add original instruction
82  			super.visitInsn(opcode);
83  			super
84  					.visitMethodInsn(INVOKESTATIC, OnTheFlyInstrumenter.TRACECLASSNAME, "arrayModified", "(Ljava/lang/Object;)V");
85  		} else {
86  			super.visitInsn(opcode);
87  		}
88  	}
89  
90  	@Override
91  	public void visitMultiANewArrayInsn(String typeDesc, int dimensions) {
92  		super.visitMultiANewArrayInsn(typeDesc, dimensions);
93  		super.visitInsn(DUP);
94  		super.visitInsn(DUP);
95  		super.visitMethodInsn(INVOKESTATIC, OnTheFlyInstrumenter.TRACECLASSNAME, "arrayCreated", "(Ljava/lang/Object;)V");
96  		super.visitLdcInsn(new Integer(dimensions - 2));
97  		super.visitMethodInsn(INVOKESTATIC, OnTheFlyInstrumenter.TRACECLASSNAME, "addArraysRecursively",
98  													"([Ljava/lang/Object;I)V");
99  	}
100 
101 }