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