KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > ch > ethz > prose > jvmai > jikesrvm > advice_weaver > JumpFinallyVisitor


1 package ch.ethz.prose.jvmai.jikesrvm.advice_weaver;
2
3 import org.apache.bcel.generic.*;
4
5 /**
6  * A visitor that adds a JSR instruction before each `return' instruction. The
7  * jump branches to a predefined finally handle.
8  * <p>
9  * This functionality is needed to implement method exit join points.
10  *
11  * @author Johann Gyger
12  */

13 public class JumpFinallyVisitor extends EmptyVisitor {
14
15   /**
16    * Method bytecode represented as a BCEL instruction list.
17    */

18   protected InstructionList code;
19
20   /**
21    * First instruction that will be visited.
22    */

23   protected InstructionHandle tryStart;
24
25   /**
26    * Last instruction that will be visited.
27    */

28   protected InstructionHandle tryEnd;
29
30   /**
31    * Branch target of JSR instruction.
32    */

33   protected InstructionHandle finallyStart;
34
35   /**
36    * Temporary instruction handle.
37    */

38   protected InstructionHandle handle;
39
40   /**
41    * Index of local variable where an eventual result of a return can be
42    * stored.
43    */

44   protected int localIndex;
45
46   /**
47    * Size of local variable.
48    */

49   protected int localSize;
50
51   /**
52    * Create a new instance of a JumpFinallyVisitor.
53    *
54    * @param code method bytecode represented as a BCEL instruction list
55    * @param tryStart first instruction that will be visited
56    * @param tryEnd last instruction that will be visited
57    * @param finallyStart branch target of JSR instruction
58    * @param localIndex index of local variable to store return result
59    */

60   public JumpFinallyVisitor(
61     InstructionList code,
62     InstructionHandle tryStart,
63     InstructionHandle tryEnd,
64     InstructionHandle finallyStart,
65     int localIndex) {
66     this.code = code;
67     this.tryStart = tryStart;
68     this.tryEnd = tryEnd;
69     this.finallyStart = finallyStart;
70     this.localIndex = localIndex;
71   }
72
73   /**
74    * Get the size of the local variable that is used to temporarily store the
75    * result.
76    *
77    * @return size of local variable
78    */

79   public int getLocalSize() {
80     return localSize;
81   }
82
83   /**
84    * Traverse list of instructions and visit each.
85    */

86   public void go() {
87     handle = tryStart;
88     while (handle.getPrev() != tryEnd) {
89       handle.getInstruction().accept(this);
90       handle = handle.getNext();
91     }
92   }
93
94   public void visitDRETURN(DRETURN obj) {
95     InstructionHandle ih = code.insert(handle, new DSTORE(localIndex + 1));
96     code.insert(handle, new JSR(finallyStart));
97     code.insert(handle, new DLOAD(localIndex + 1));
98
99     retarget(ih);
100     localSize = obj.getType().getSize();
101   }
102
103   public void visitRETURN(RETURN obj) {
104     InstructionHandle ih = code.insert(handle, new JSR(finallyStart));
105
106     retarget(ih);
107   }
108
109   public void visitLRETURN(LRETURN obj) {
110     InstructionHandle ih = code.insert(handle, new LSTORE(localIndex + 1));
111     code.insert(handle, new JSR(finallyStart));
112     code.insert(handle, new LLOAD(localIndex + 1));
113
114     retarget(ih);
115     localSize = obj.getType().getSize();
116   }
117
118   public void visitIRETURN(IRETURN obj) {
119     InstructionHandle ih = code.insert(handle, new ISTORE(localIndex + 1));
120     code.insert(handle, new JSR(finallyStart));
121     code.insert(handle, new ILOAD(localIndex + 1));
122
123     retarget(ih);
124     localSize = obj.getType().getSize();
125   }
126
127   public void visitARETURN(ARETURN obj) {
128     InstructionHandle ih = code.insert(handle, new ASTORE(localIndex + 1));
129     code.insert(handle, new JSR(finallyStart));
130     code.insert(handle, new ALOAD(localIndex + 1));
131
132     retarget(ih);
133     localSize = obj.getType().getSize();
134   }
135
136   public void visitFRETURN(FRETURN obj) {
137     InstructionHandle ih = code.insert(handle, new FSTORE(localIndex + 1));
138     code.insert(handle, new JSR(finallyStart));
139     code.insert(handle, new FLOAD(localIndex + 1));
140
141     retarget(ih);
142     localSize = obj.getType().getSize();
143   }
144
145   /**
146    * Retarget all branch instructions to `newTarget'.
147    *
148    * @param newTarget new target
149    */

150   protected void retarget(InstructionHandle newTarget) {
151     if (handle.hasTargeters()) {
152       InstructionTargeter[] its = handle.getTargeters();
153       for (int i = 0; i < its.length; i++)
154         if (its[i] instanceof BranchInstruction)
155           its[i].updateTarget(handle, newTarget);
156     }
157   }
158   
159 }
160
Popular Tags