Source code: com/techtrader/modules/tools/bytecode/StackInstruction.java
1 package com.techtrader.modules.tools.bytecode;
2
3
4 import com.techtrader.modules.tools.bytecode.visitor.BCVisitor;
5
6
7 /**
8 * Represents an instruction that manipulates the stack of the current
9 * frame. Using the setType methods is a hint about the type being
10 * manipulated that might cause this Instruction to use the wide version
11 * of the opcode it represents (if manipulating a long or double). This
12 * saves the developer from having to decide at compile time whether to
13 * use pop() or pop2(), etc.
14 *
15 * @author Abe White
16 */
17 public class StackInstruction
18 extends Instruction
19 {
20 protected StackInstruction (Code owner, int opcode)
21 {
22 super (owner);
23 _opcode = opcode;
24 }
25
26
27 /**
28 * Set the type that is being manipulated; this might cause the
29 * instruction to change to the wide version of the opcode it represents.
30 *
31 * @return this Instruction, for method chaining
32 */
33 public StackInstruction setType (Class type)
34 {
35 boolean wide = type.equals (long.class) || type.equals (double.class);
36 calculateOpCode (wide);
37 return this;
38 }
39
40
41 /**
42 * Set the type to manipulate by name.
43 *
44 * @return this Instruction, for method chaining
45 *
46 * @see #setType(java.lang.Class)
47 */
48 public StackInstruction setTypeName (String name)
49 {
50 boolean wide = name.equals ("long") || name.equals ("double");
51 calculateOpCode (wide);
52 return this;
53 }
54
55
56 public int getStackChange ()
57 {
58 switch (_opcode)
59 {
60 case POP:
61 return -1;
62
63 case POP2:
64 return -2;
65
66 case DUP:
67 case DUP_X1:
68 case DUP_X2:
69 return 1;
70
71 case DUP2:
72 case DUP2_X1:
73 case DUP2_X2:
74 return 2;
75
76 default:
77 return 0;
78 }
79 }
80
81
82 /**
83 * Helper method to change the opcode of this instruction if need be.
84 */
85 private void calculateOpCode (boolean wide)
86 {
87 switch (_opcode)
88 {
89 case POP:
90 if (wide) _opcode = POP2;
91 break;
92 case POP2:
93 if (!wide) _opcode = POP;
94 break;
95 case DUP:
96 if (wide) _opcode = DUP2;
97 break;
98 case DUP2:
99 if (!wide) _opcode = DUP;
100 break;
101 case DUP_X1:
102 if (wide) _opcode = DUP2_X1;
103 break;
104 case DUP2_X1:
105 if (!wide) _opcode = DUP_X1;
106 break;
107 case DUP_X2:
108 if (wide) _opcode = DUP2_X2;
109 break;
110 case DUP2_X2:
111 if (!wide) _opcode = DUP_X2;
112 break;
113 }
114 }
115
116
117 public void acceptVisit (BCVisitor visit)
118 {
119 visit.enterStackInstruction (this);
120 visit.exitStackInstruction (this);
121 }
122 }