001/* 002 * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package com.oracle.graal.graph; 024 025import java.util.AbstractMap.SimpleEntry; 026import java.util.*; 027import java.util.Map.Entry; 028 029public class NodeMap<T> extends NodeIdAccessor { 030 031 private static final int MIN_REALLOC_SIZE = 16; 032 033 protected Object[] values; 034 035 public NodeMap(Graph graph) { 036 super(graph); 037 this.values = new Object[graph.nodeIdCount()]; 038 } 039 040 public NodeMap(NodeMap<T> copyFrom) { 041 super(copyFrom.graph); 042 this.values = Arrays.copyOf(copyFrom.values, copyFrom.values.length); 043 } 044 045 @SuppressWarnings("unchecked") 046 public T get(Node node) { 047 assert check(node); 048 return (T) values[getNodeId(node)]; 049 } 050 051 @SuppressWarnings("unchecked") 052 public T getAndGrow(Node node) { 053 checkAndGrow(node); 054 return (T) values[getNodeId(node)]; 055 } 056 057 private void checkAndGrow(Node node) { 058 if (isNew(node)) { 059 this.values = Arrays.copyOf(values, Math.max(MIN_REALLOC_SIZE, graph.nodeIdCount() * 3 / 2)); 060 } 061 assert check(node); 062 } 063 064 public boolean isEmpty() { 065 return !entries().iterator().hasNext(); 066 } 067 068 public boolean containsKey(Object key) { 069 if (key instanceof Node) { 070 Node node = (Node) key; 071 if (node.graph() == graph()) { 072 return get(node) != null; 073 } 074 } 075 return false; 076 } 077 078 public boolean containsValue(Object value) { 079 for (Object o : values) { 080 if (o == value) { 081 return true; 082 } 083 } 084 return false; 085 } 086 087 public Graph graph() { 088 return graph; 089 } 090 091 public void set(Node node, T value) { 092 assert check(node); 093 values[getNodeId(node)] = value; 094 } 095 096 public void setAndGrow(Node node, T value) { 097 checkAndGrow(node); 098 values[getNodeId(node)] = value; 099 } 100 101 /** 102 * @param i 103 * @return Return the key for the entry at index {@code i} 104 */ 105 protected Node getKey(int i) { 106 return graph.getNode(i); 107 } 108 109 public int size() { 110 return values.length; 111 } 112 113 public boolean isNew(Node node) { 114 return getNodeId(node) >= size(); 115 } 116 117 private boolean check(Node node) { 118 assert node.graph() == graph : String.format("%s is not part of the graph", node); 119 assert !isNew(node) : "this node was added to the graph after creating the node map : " + node; 120 return true; 121 } 122 123 public void clear() { 124 Arrays.fill(values, null); 125 } 126 127 public Iterable<Entry<Node, T>> entries() { 128 return new Iterable<Entry<Node, T>>() { 129 130 @Override 131 public Iterator<Entry<Node, T>> iterator() { 132 return new Iterator<Entry<Node, T>>() { 133 134 int i = 0; 135 136 @Override 137 public boolean hasNext() { 138 forward(); 139 return i < NodeMap.this.values.length; 140 } 141 142 @SuppressWarnings("unchecked") 143 @Override 144 public Entry<Node, T> next() { 145 final int pos = i; 146 Node key = NodeMap.this.getKey(pos); 147 T value = (T) NodeMap.this.values[pos]; 148 i++; 149 forward(); 150 return new SimpleEntry<Node, T>(key, value) { 151 152 private static final long serialVersionUID = 7813842391085737738L; 153 154 @Override 155 public T setValue(T v) { 156 T oldv = super.setValue(v); 157 NodeMap.this.values[pos] = v; 158 return oldv; 159 } 160 }; 161 } 162 163 @Override 164 public void remove() { 165 throw new UnsupportedOperationException(); 166 } 167 168 private void forward() { 169 while (i < NodeMap.this.values.length && (NodeMap.this.getKey(i) == null || NodeMap.this.values[i] == null)) { 170 i++; 171 } 172 } 173 }; 174 } 175 }; 176 } 177 178 @Override 179 public String toString() { 180 Iterator<Entry<Node, T>> i = entries().iterator(); 181 if (!i.hasNext()) { 182 return "{}"; 183 } 184 185 StringBuilder sb = new StringBuilder(); 186 sb.append('{'); 187 while (true) { 188 Entry<Node, T> e = i.next(); 189 Node key = e.getKey(); 190 T value = e.getValue(); 191 sb.append(key); 192 sb.append('='); 193 sb.append(value); 194 if (!i.hasNext()) { 195 return sb.append('}').toString(); 196 } 197 sb.append(',').append(' '); 198 } 199 } 200}