1 package serp.bytecode;
2
3 /***
4 * InstructionPtrStrategy handles the different strategies for finding the
5 * Instructions that InstructionPtrs point to. These strategies include,
6 * from least desirable to most desirable, using byte indexes,
7 * and storing a reference to the target Instruction proper.
8 *
9 * @author Eric Lindauer
10 * @date 2002.7.26
11 */
12 class InstructionPtrStrategy implements InstructionPtr {
13
14 private InstructionPtr _pointer;
15
16
17
18 private Instruction _target = null;
19 private int _byteIndex = -1;
20
21 public InstructionPtrStrategy(InstructionPtr pointer) {
22 _pointer = pointer;
23 }
24
25 public InstructionPtrStrategy(InstructionPtr pointer, Instruction target) {
26 this(pointer);
27 setTargetInstruction(target);
28 }
29
30 /***
31 * Sets the byteIndex where the target Instruction can be found.
32 * This target will now be using byte indices as its target finding
33 * strategy, which is the least robust option. Changing the Code block
34 * or importing it into another Method may result in an invalid target.
35 */
36 public void setByteIndex(int index) {
37 if (index < -1)
38 throw new IllegalArgumentException(String.valueOf(index));
39 _byteIndex = index;
40 _target = null;
41 }
42
43 /***
44 * Changes the target Instruction. The target is in the best state
45 * possible and should maintain this information even in the face
46 * of Code imports and Code changes.
47 */
48 public void setTargetInstruction(Instruction ins) {
49 if (ins.getCode() != getCode())
50 throw new IllegalArgumentException("Instruction pointers and "
51 + "targets must be part of the same code block.");
52 _target = ins;
53 _byteIndex = -1;
54 }
55
56 /***
57 * Returns the Instruction this Target is targetting. This request
58 * does not change the targetting strategy for this Target.
59 */
60 public Instruction getTargetInstruction() {
61 if (_target != null)
62 return _target;
63 return getCode().getInstruction(_byteIndex);
64 }
65
66 /***
67 * Returns the byteIndex at which the target instruction can be found.
68 * This call does not change the Target strategy.
69 */
70 public int getByteIndex() {
71 if (_target == null)
72 return _byteIndex;
73 return _target.getByteIndex();
74 }
75
76 /***
77 * Same as getInstruction, but this method alters the Target strategy
78 * to use the returned Instruction. This method alters the Target
79 * strategy (and Instruction) iff it was previously using byte indexes.
80 */
81 public void updateTargets() {
82 if (_target == null)
83 _target = getCode().getInstruction(_byteIndex);
84 }
85
86 public void replaceTarget(Instruction oldTarget, Instruction newTarget) {
87 if (getTargetInstruction() == oldTarget)
88 setTargetInstruction(newTarget);
89 }
90
91 public Code getCode() {
92 return _pointer.getCode();
93 }
94 }