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.forward.analysis;
18
19 import java.util.HashSet;
20 import java.util.Set;
21
22 import org.objectweb.asm.Type;
23 import org.objectweb.asm.tree.AbstractInsnNode;
24 import org.objectweb.asm.tree.analysis.Value;
25
26 /** A value that keep track of both instructions producing and consuming it.
27 * @version $Id$
28 */
29 public class TrackingValue implements Value {
30
31 /** Special value for uninitialized values. */
32 public static final TrackingValue UNINITIALIZED_VALUE = new TrackingValue(null);
33
34 /** Value type. */
35 private final Type type;
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 (including the instance itself). */
44 private Set<TrackingValue> merged;
45
46 /** Build a new value without any link to instructions.
47 * @param type value type
48 */
49 public TrackingValue(final Type type) {
50 this.type = type;
51 consumers = new HashSet<AbstractInsnNode>();
52 producers = new HashSet<AbstractInsnNode>();
53 merged = new HashSet<TrackingValue>();
54 merged.add(this);
55 }
56
57 /** Build a new value produced by a specified instruction.
58 * @param type value type
59 * @param producer producer for this value
60 */
61 public TrackingValue(final Type type, final AbstractInsnNode producer) {
62 this(type);
63 producers.add(producer);
64 }
65
66 /** Get the value type.
67 * @return value type
68 */
69 public Type getType() {
70 return type;
71 }
72
73 /** {@inheritDoc} */
74 public int getSize() {
75 return type == Type.LONG_TYPE || type == Type.DOUBLE_TYPE ? 2 : 1;
76 }
77
78 /** Add a consumer for this value.
79 * @param consumer consumer for this value
80 */
81 public void addConsumer(final AbstractInsnNode consumer) {
82 consumers.add(consumer);
83 }
84
85 /** Get the consumers for this value and all values it is merged with.
86 * @return the instructions consuming either this value or the values
87 * it has been merged with
88 */
89 public Set<AbstractInsnNode> getConsumers() {
90 return consumers;
91 }
92
93 /** Add a producer for this value.
94 * @param producer producer for this value
95 */
96 public void addProducer(final AbstractInsnNode producer) {
97 producers.add(producer);
98 }
99
100 /** Get the producers for this value and all values it is merged with.
101 * @return the instructions producing either this value or the values
102 * it has been merged with
103 */
104 public Set<AbstractInsnNode> getProducers() {
105 return producers;
106 }
107
108 /** Merge two instances.
109 * <p>Once merged, values share the same producers and consumers sets.</p>
110 * @param value1 first value to merge
111 * @param value2 second value to merge
112 */
113 public static void merge(final TrackingValue value1, final TrackingValue value2) {
114
115 if (value1.merged.contains(value2)) {
116 // the values have already been merged
117 return;
118 }
119
120 // merge the sets
121 value1.consumers.addAll(value2.consumers);
122 value1.producers.addAll(value2.producers);
123 value1.merged.addAll(value2.merged);
124
125 // share the merged sets
126 for (final TrackingValue value : value2.merged) {
127 value.consumers = value1.consumers;
128 value.producers = value1.producers;
129 value.merged = value1.merged;
130 }
131
132 }
133
134 }