11package software .coley .recaf .util .analysis ;
22
3+ import jakarta .annotation .Nonnull ;
34import org .objectweb .asm .Opcodes ;
45import org .objectweb .asm .tree .AbstractInsnNode ;
56import org .objectweb .asm .tree .analysis .AnalyzerException ;
1415 * @author Matt Coley
1516 */
1617public class ReFrame extends Frame <ReValue > {
18+ /**
19+ * New frame with the given number of expected locals/stack-slots.
20+ *
21+ * @param numLocals
22+ * Available local variable slots.
23+ * @param maxStack
24+ * Available stack slots.
25+ */
1726 public ReFrame (int numLocals , int maxStack ) {
1827 super (numLocals , maxStack );
1928 }
2029
21- public ReFrame (Frame <? extends ReValue > frame ) {
30+ /**
31+ * New frame copying the state of the given frame.
32+ *
33+ * @param frame
34+ * Frame to copy stack/locals of.
35+ */
36+ public ReFrame (@ Nonnull Frame <? extends ReValue > frame ) {
2237 super (frame );
2338 }
2439
@@ -38,29 +53,40 @@ public void execute(AbstractInsnNode insn, Interpreter<ReValue> interpreter) thr
3853 ReValue index = pop ();
3954 ReValue array = pop ();
4055 ReValue updatedArray = interpreter .ternaryOperation (insn , array , index , value );
41- if (updatedArray != array ) {
42- for (int i = 0 ; i < getStackSize (); i ++) {
43- ReValue stack = getStack (i );
44- if (stack == array ) {
45- setStack (i , updatedArray );
46- } else if (stack instanceof ArrayValue stackArray ) {
47- ArrayValue updatedStackArray = stackArray .updatedCopyIfContained (array , updatedArray );
48- setStack (i , updatedStackArray );
49- }
50- }
51- for (int i = 0 ; i < getLocals (); i ++) {
52- ReValue local = getLocal (i );
53- if (local == array ) {
54- setLocal (i , updatedArray );
55- } else if (local instanceof ArrayValue stackArray ) {
56- ArrayValue updatedStackArray = stackArray .updatedCopyIfContained (array , updatedArray );
57- setLocal (i , updatedStackArray );
58- }
59- }
60- }
56+ if (updatedArray != array )
57+ replaceValue (array , updatedArray );
6158 break ;
6259 default :
6360 super .execute (insn , interpreter );
6461 }
6562 }
63+
64+ /**
65+ * Replace all references to the given value with the replacement.
66+ *
67+ * @param existing
68+ * Some existing value that exists in this frame.
69+ * @param replacement
70+ * Instance to replace the existing value with.
71+ */
72+ public void replaceValue (@ Nonnull ReValue existing , @ Nonnull ReValue replacement ) {
73+ for (int i = 0 ; i < getStackSize (); i ++) {
74+ ReValue stack = getStack (i );
75+ if (stack == existing ) {
76+ setStack (i , replacement );
77+ } else if (stack instanceof ArrayValue stackArray ) {
78+ ArrayValue updatedStackArray = stackArray .updatedCopyIfContained (existing , replacement );
79+ setStack (i , updatedStackArray );
80+ }
81+ }
82+ for (int i = 0 ; i < getLocals (); i ++) {
83+ ReValue local = getLocal (i );
84+ if (local == existing ) {
85+ setLocal (i , replacement );
86+ } else if (local instanceof ArrayValue stackArray ) {
87+ ArrayValue updatedStackArray = stackArray .updatedCopyIfContained (existing , replacement );
88+ setLocal (i , updatedStackArray );
89+ }
90+ }
91+ }
6692}
0 commit comments