001/* 002 * Copyright (c) 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.*; 026 027import com.oracle.graal.graph.iterators.*; 028 029public abstract class NodeList<T extends Node> extends AbstractList<T> implements NodeIterable<T>, RandomAccess { 030 031 protected static final Node[] EMPTY_NODE_ARRAY = new Node[0]; 032 033 protected final Node self; 034 protected Node[] nodes; 035 private int size; 036 protected final int initialSize; 037 038 protected NodeList(Node self) { 039 this.self = self; 040 this.nodes = EMPTY_NODE_ARRAY; 041 this.initialSize = 0; 042 } 043 044 protected NodeList(Node self, int initialSize) { 045 this.self = self; 046 this.size = initialSize; 047 this.initialSize = initialSize; 048 this.nodes = new Node[initialSize]; 049 } 050 051 protected NodeList(Node self, T[] elements) { 052 this.self = self; 053 if (elements == null || elements.length == 0) { 054 this.size = 0; 055 this.nodes = EMPTY_NODE_ARRAY; 056 this.initialSize = 0; 057 } else { 058 this.size = elements.length; 059 this.initialSize = elements.length; 060 this.nodes = new Node[elements.length]; 061 for (int i = 0; i < elements.length; i++) { 062 this.nodes[i] = elements[i]; 063 assert this.nodes[i] == null || !this.nodes[i].isDeleted() : "Initializing nodelist with deleted element : " + nodes[i]; 064 } 065 } 066 } 067 068 protected NodeList(Node self, List<? extends T> elements) { 069 this.self = self; 070 if (elements == null || elements.isEmpty()) { 071 this.size = 0; 072 this.nodes = EMPTY_NODE_ARRAY; 073 this.initialSize = 0; 074 } else { 075 this.size = elements.size(); 076 this.initialSize = elements.size(); 077 this.nodes = new Node[elements.size()]; 078 for (int i = 0; i < elements.size(); i++) { 079 this.nodes[i] = elements.get(i); 080 assert this.nodes[i] == null || !this.nodes[i].isDeleted(); 081 } 082 } 083 } 084 085 protected NodeList(Node self, Collection<? extends NodeInterface> elements) { 086 this.self = self; 087 if (elements == null || elements.isEmpty()) { 088 this.size = 0; 089 this.nodes = EMPTY_NODE_ARRAY; 090 this.initialSize = 0; 091 } else { 092 this.size = elements.size(); 093 this.initialSize = elements.size(); 094 this.nodes = new Node[elements.size()]; 095 int i = 0; 096 for (NodeInterface n : elements) { 097 this.nodes[i] = n.asNode(); 098 assert this.nodes[i] == null || !this.nodes[i].isDeleted(); 099 i++; 100 } 101 } 102 } 103 104 public boolean isList() { 105 return true; 106 } 107 108 protected abstract void update(T oldNode, T newNode); 109 110 public abstract Edges.Type getEdgesType(); 111 112 @Override 113 public final int size() { 114 return size; 115 } 116 117 @Override 118 public final boolean isEmpty() { 119 return size == 0; 120 } 121 122 @Override 123 public boolean isNotEmpty() { 124 return size > 0; 125 } 126 127 @Override 128 public int count() { 129 return size; 130 } 131 132 protected final void incModCount() { 133 modCount++; 134 } 135 136 @SuppressWarnings("unchecked") 137 @Override 138 public boolean add(Node node) { 139 assert node == null || !node.isDeleted(); 140 self.incModCount(); 141 incModCount(); 142 int length = nodes.length; 143 if (length == 0) { 144 nodes = new Node[2]; 145 } else if (size == length) { 146 Node[] newNodes = new Node[nodes.length * 2 + 1]; 147 System.arraycopy(nodes, 0, newNodes, 0, length); 148 nodes = newNodes; 149 } 150 nodes[size++] = node; 151 update(null, (T) node); 152 return true; 153 } 154 155 @Override 156 @SuppressWarnings("unchecked") 157 public T get(int index) { 158 assert assertInRange(index); 159 return (T) nodes[index]; 160 } 161 162 private boolean assertInRange(int index) { 163 assert index < size() : index + " < " + size(); 164 return true; 165 } 166 167 public T last() { 168 return get(size() - 1); 169 } 170 171 @Override 172 @SuppressWarnings("unchecked") 173 public T set(int index, Node node) { 174 incModCount(); 175 T oldValue = (T) nodes[index]; 176 assert assertInRange(index); 177 update((T) nodes[index], (T) node); 178 nodes[index] = node; 179 return oldValue; 180 } 181 182 public void initialize(int index, Node node) { 183 incModCount(); 184 assert index < size(); 185 nodes[index] = node; 186 } 187 188 void copy(NodeList<? extends Node> other) { 189 self.incModCount(); 190 incModCount(); 191 Node[] newNodes = new Node[other.size]; 192 System.arraycopy(other.nodes, 0, newNodes, 0, newNodes.length); 193 nodes = newNodes; 194 size = other.size; 195 } 196 197 public boolean equals(NodeList<T> other) { 198 if (size != other.size) { 199 return false; 200 } 201 for (int i = 0; i < size; i++) { 202 if (nodes[i] != other.nodes[i]) { 203 return false; 204 } 205 } 206 return true; 207 } 208 209 @SuppressWarnings("unchecked") 210 @Override 211 public void clear() { 212 self.incModCount(); 213 incModCount(); 214 for (int i = 0; i < size; i++) { 215 update((T) nodes[i], null); 216 } 217 nodes = EMPTY_NODE_ARRAY; 218 size = 0; 219 } 220 221 @Override 222 @SuppressWarnings("unchecked") 223 public boolean remove(Object node) { 224 self.incModCount(); 225 int i = 0; 226 incModCount(); 227 while (i < size && nodes[i] != node) { 228 i++; 229 } 230 if (i < size) { 231 T oldValue = (T) nodes[i]; 232 i++; 233 while (i < size) { 234 nodes[i - 1] = nodes[i]; 235 i++; 236 } 237 nodes[--size] = null; 238 update(oldValue, null); 239 return true; 240 } else { 241 return false; 242 } 243 } 244 245 @Override 246 @SuppressWarnings("unchecked") 247 public T remove(int index) { 248 self.incModCount(); 249 T oldValue = (T) nodes[index]; 250 int i = index + 1; 251 incModCount(); 252 while (i < size) { 253 nodes[i - 1] = nodes[i]; 254 i++; 255 } 256 nodes[--size] = null; 257 update(oldValue, null); 258 return oldValue; 259 } 260 261 boolean replaceFirst(Node node, Node other) { 262 for (int i = 0; i < size; i++) { 263 if (nodes[i] == node) { 264 nodes[i] = other; 265 return true; 266 } 267 } 268 return false; 269 } 270 271 @Override 272 public Iterator<T> iterator() { 273 return new Iterator<T>() { 274 275 private final int expectedModCount = NodeList.this.modCount; 276 private int index = 0; 277 278 @Override 279 public boolean hasNext() { 280 assert expectedModCount == NodeList.this.modCount; 281 return index < NodeList.this.size; 282 } 283 284 @SuppressWarnings("unchecked") 285 @Override 286 public T next() { 287 assert expectedModCount == NodeList.this.modCount; 288 return (T) NodeList.this.nodes[index++]; 289 } 290 291 @Override 292 public void remove() { 293 throw new UnsupportedOperationException(); 294 } 295 }; 296 } 297 298 @Override 299 public boolean contains(T other) { 300 for (int i = 0; i < size; i++) { 301 if (nodes[i] == other) { 302 return true; 303 } 304 } 305 return false; 306 } 307 308 @SuppressWarnings("unchecked") 309 @Override 310 public List<T> snapshot() { 311 return (List<T>) Arrays.asList(Arrays.copyOf(this.nodes, this.size)); 312 } 313 314 @Override 315 public void snapshotTo(Collection<? super T> to) { 316 for (int i = 0; i < size; i++) { 317 to.add(get(i)); 318 } 319 } 320 321 @SuppressWarnings("unchecked") 322 public void setAll(NodeList<T> values) { 323 self.incModCount(); 324 incModCount(); 325 for (int i = 0; i < size(); i++) { 326 update((T) nodes[i], null); 327 } 328 nodes = Arrays.copyOf(values.nodes, values.size()); 329 size = values.size(); 330 331 for (int i = 0; i < size(); i++) { 332 update(null, (T) nodes[i]); 333 } 334 } 335 336 @Override 337 @SuppressWarnings("unchecked") 338 public <A> A[] toArray(A[] a) { 339 if (a.length >= size) { 340 System.arraycopy(nodes, 0, a, 0, size); 341 return a; 342 } 343 return (A[]) Arrays.copyOf(nodes, size, a.getClass()); 344 } 345 346 @Override 347 public Object[] toArray() { 348 return Arrays.copyOf(nodes, size); 349 } 350 351 protected void replace(T node, T other) { 352 incModCount(); 353 for (int i = 0; i < size(); i++) { 354 if (nodes[i] == node) { 355 nodes[i] = other; 356 update(node, other); 357 } 358 } 359 } 360 361 @Override 362 public int indexOf(Object node) { 363 for (int i = 0; i < size; i++) { 364 if (nodes[i] == node) { 365 return i; 366 } 367 } 368 return -1; 369 } 370 371 @Override 372 public boolean contains(Object o) { 373 return indexOf(o) != -1; 374 } 375 376 @Override 377 public boolean containsAll(Collection<?> c) { 378 throw new UnsupportedOperationException("not implemented"); 379 } 380 381 @Override 382 public boolean addAll(Collection<? extends T> c) { 383 for (T e : c) { 384 add(e); 385 } 386 return true; 387 } 388 389 public boolean addAll(T[] c) { 390 for (T e : c) { 391 add(e); 392 } 393 return true; 394 } 395 396 @Override 397 public String toString() { 398 StringBuilder sb = new StringBuilder(); 399 sb.append('['); 400 for (int i = 0; i < size; i++) { 401 if (i != 0) { 402 sb.append(", "); 403 } 404 sb.append(nodes[i]); 405 } 406 sb.append(']'); 407 return sb.toString(); 408 } 409 410 @Override 411 public T first() { 412 if (size() > 0) { 413 return get(0); 414 } 415 return null; 416 } 417}