001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.commons.nabla.forward.analysis; 018 019 import java.util.HashSet; 020 import java.util.Set; 021 022 import org.objectweb.asm.Type; 023 import org.objectweb.asm.tree.AbstractInsnNode; 024 import org.objectweb.asm.tree.analysis.Value; 025 026 /** A value that keep track of both instructions producing and consuming it. 027 * @version $Id$ 028 */ 029 public class TrackingValue implements Value { 030 031 /** Special value for uninitialized values. */ 032 public static final TrackingValue UNINITIALIZED_VALUE = new TrackingValue(null); 033 034 /** Value type. */ 035 private final Type type; 036 037 /** Instructions that consume this value. */ 038 private Set<AbstractInsnNode> consumers; 039 040 /** Instructions that produce this value. */ 041 private Set<AbstractInsnNode> producers; 042 043 /** Values that are merged with this value (including the instance itself). */ 044 private Set<TrackingValue> merged; 045 046 /** Build a new value without any link to instructions. 047 * @param type value type 048 */ 049 public TrackingValue(final Type type) { 050 this.type = type; 051 consumers = new HashSet<AbstractInsnNode>(); 052 producers = new HashSet<AbstractInsnNode>(); 053 merged = new HashSet<TrackingValue>(); 054 merged.add(this); 055 } 056 057 /** Build a new value produced by a specified instruction. 058 * @param type value type 059 * @param producer producer for this value 060 */ 061 public TrackingValue(final Type type, final AbstractInsnNode producer) { 062 this(type); 063 producers.add(producer); 064 } 065 066 /** Get the value type. 067 * @return value type 068 */ 069 public Type getType() { 070 return type; 071 } 072 073 /** {@inheritDoc} */ 074 public int getSize() { 075 return type == Type.LONG_TYPE || type == Type.DOUBLE_TYPE ? 2 : 1; 076 } 077 078 /** Add a consumer for this value. 079 * @param consumer consumer for this value 080 */ 081 public void addConsumer(final AbstractInsnNode consumer) { 082 consumers.add(consumer); 083 } 084 085 /** Get the consumers for this value and all values it is merged with. 086 * @return the instructions consuming either this value or the values 087 * it has been merged with 088 */ 089 public Set<AbstractInsnNode> getConsumers() { 090 return consumers; 091 } 092 093 /** Add a producer for this value. 094 * @param producer producer for this value 095 */ 096 public void addProducer(final AbstractInsnNode producer) { 097 producers.add(producer); 098 } 099 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 }