1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.commons.nabla.algorithmic.forward.analysis;
18
19 import java.util.HashSet;
20 import java.util.Set;
21
22 import org.objectweb.asm.tree.AbstractInsnNode;
23 import org.objectweb.asm.tree.analysis.BasicValue;
24 import org.objectweb.asm.tree.analysis.Value;
25
26 /** A value that keep track of both instructions producing and consuming it.
27 */
28 public class TrackingValue implements Value {
29
30 /** Special value for uninitialized values. */
31 public static final TrackingValue UNINITIALIZED_VALUE =
32 new TrackingValue((BasicValue) BasicValue.UNINITIALIZED_VALUE);
33
34 /** Underlying value. */
35 private final BasicValue value;
36
37 /** Instructions that consume this value. */
38 private Set<AbstractInsnNode> consumers;
39
40 /** Instructions that produce this value. */
41 private Set<AbstractInsnNode> producers;
42
43 /** Values that are merged with this value. */
44 private Set<TrackingValue> merged;
45
46 /** Build a new value without any link to instructions.
47 * @param value wrapped {@link BasicValue} value
48 */
49 public TrackingValue(final BasicValue value) {
50 this.value = value;
51 consumers = new HashSet<AbstractInsnNode>();
52 producers = new HashSet<AbstractInsnNode>();
53 merged = new HashSet<TrackingValue>();
54 }
55
56 /** Get the wrapped {@link BasicValue}.
57 * @return wrapped {@link BasicValue}
58 */
59 public BasicValue getValue() {
60 return value;
61 }
62
63 /** {@inheritDoc} */
64 public int getSize() {
65 return value.getSize();
66 }
67
68 /** Add a consumer for this value.
69 * @param consumer consumer for this value
70 */
71 public void addConsumer(final AbstractInsnNode consumer) {
72 consumers.add(consumer);
73 }
74
75 /** Get the consumers for this value and all values it is merged with.
76 * @return the instructions consuming either this value or the values
77 * it has been merged with
78 */
79 public Set<AbstractInsnNode> getConsumers() {
80 return consumers;
81 }
82
83 /** Add a producer for this value.
84 * @param producer producer for this value
85 */
86 public void addProducer(final AbstractInsnNode producer) {
87 producers.add(producer);
88 }
89
90 /** Get the producers for this value and all values it is merged with.
91 * @return the instructions producing either this value or the values
92 * it has been merged with
93 */
94 public Set<AbstractInsnNode> getProducers() {
95 return producers;
96 }
97
98 /** Merge two instances.
99 * <p>Once merged, values share the same producers and consumers sets.</p>
100 * @param value1 first value to merge
101 * @param value2 second value to merge
102 */
103 public static void merge(final TrackingValue value1,
104 final TrackingValue value2) {
105
106 // merge the sets
107 value1.consumers.addAll(value2.consumers);
108 value1.producers.addAll(value2.producers);
109 value1.merged.addAll(value2.merged);
110
111 // share the merged sets
112 for (TrackingValue value : value2.merged) {
113 value.consumers = value1.consumers;
114 value.producers = value1.producers;
115 value.merged = value1.merged;
116 }
117 value2.consumers = value1.consumers;
118 value2.producers = value1.producers;
119 value2.merged = value1.merged;
120
121 }
122
123 }