View Javadoc

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.automatic.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 }