# HG changeset patch # User Doug Simon # Date 1416059199 -3600 # Node ID 601dfbdcc5bf9f225878e66ac5b70524323386e7 # Parent 3aaf2747961cc9a805aa050aaae6751302d788d0 added LinkedIdentityHashMap diff -r 3aaf2747961c -r 601dfbdcc5bf graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/remote/LinkedIdentityHashMap.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/remote/LinkedIdentityHashMap.java Sat Nov 15 14:46:39 2014 +0100 @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.common.remote; + +import java.util.*; +import java.util.function.*; + +import com.oracle.graal.compiler.common.remote.Context.Mode; + +/** + * A map that combines {@link IdentityHashMap} with {@link LinkedHashMap} for the purpose of + * ensuring a deterministic execution order during {@link Mode#Capturing}. + */ +final class LinkedIdentityHashMap implements Map { + + private final LinkedHashMap, V> map; + + public LinkedIdentityHashMap() { + map = new LinkedHashMap<>(); + } + + public LinkedIdentityHashMap(Map m) { + map = new LinkedHashMap<>(m.size()); + putAll(m); + } + + public LinkedIdentityHashMap(int expectedMaxSize) { + map = new LinkedHashMap<>(expectedMaxSize); + } + + /** + * Wrapper for an object that gives uses the object's identity for the purpose of equality + * comparisons and computing a hash code. + */ + public static class Id { + final T object; + + public Id(T object) { + assert object != null; + this.object = object; + } + + @SuppressWarnings("unchecked") + @Override + public boolean equals(Object obj) { + return ((Id) obj).object == object; + } + + @Override + public int hashCode() { + return System.identityHashCode(object); + } + } + + public int size() { + return map.size(); + } + + public boolean isEmpty() { + return map.isEmpty(); + } + + public boolean containsKey(Object key) { + return map.containsKey(id(key)); + } + + @SuppressWarnings("unchecked") + private Id id(Object key) { + if (key == null) { + return null; + } + return new Id<>((K) key); + } + + public boolean containsValue(Object value) { + return map.containsValue(value); + } + + public V get(Object key) { + return map.get(id(key)); + } + + public V put(K key, V value) { + return map.put(id(key), value); + } + + public V remove(Object key) { + return map.remove(id(key)); + } + + @SuppressWarnings("unchecked") + public void putAll(Map m) { + if (m != null && m.getClass() == getClass()) { + LinkedIdentityHashMap that = (LinkedIdentityHashMap) m; + map.putAll(that.map); + + } else { + for (K key : m.keySet()) { + map.put(id(key), m.get(key)); + } + } + } + + public void clear() { + map.clear(); + } + + final class KeySet extends AbstractSet { + @Override + public int size() { + return map.size(); + } + + @Override + public void clear() { + map.clear(); + } + + @Override + public Iterator iterator() { + return new Iterator() { + final Iterator> i = map.keySet().iterator(); + + public boolean hasNext() { + return i.hasNext(); + } + + public K next() { + return i.next().object; + } + + public void remove() { + i.remove(); + } + }; + } + + @Override + public boolean contains(Object o) { + return containsKey(o); + } + + @Override + public boolean remove(Object o) { + return LinkedIdentityHashMap.this.remove(o) != null; + } + + public Spliterator spliterator() { + return Spliterators.spliterator(this, Spliterator.SIZED | Spliterator.ORDERED | Spliterator.DISTINCT); + } + + public void forEach(Consumer action) { + throw new UnsupportedOperationException(); + } + } + + public Set keySet() { + return new KeySet(); + } + + public Collection values() { + return map.values(); + } + + final class EntrySet extends AbstractSet> { + @Override + public int size() { + return map.size(); + } + + @Override + public void clear() { + map.clear(); + } + + @Override + public Iterator> iterator() { + return new Iterator>() { + final Iterator, V>> i = map.entrySet().iterator(); + + public boolean hasNext() { + return i.hasNext(); + } + + public Map.Entry next() { + Map.Entry, V> e = i.next(); + return new Map.Entry() { + + public K getKey() { + return e.getKey().object; + } + + public V getValue() { + return e.getValue(); + } + + public V setValue(V value) { + return e.setValue(value); + } + }; + } + + public void remove() { + i.remove(); + } + }; + } + + @Override + public boolean contains(Object o) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean remove(Object o) { + throw new UnsupportedOperationException(); + } + + public Spliterator> spliterator() { + throw new UnsupportedOperationException(); + } + + public void forEach(Consumer> action) { + throw new UnsupportedOperationException(); + } + } + + public Set> entrySet() { + return new EntrySet(); + } +}