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 }