--- /dev/null 2016-05-31 09:42:47.975716356 -0700 +++ new/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/LinkedIdentityHashMap.java 2016-12-07 13:47:52.553185676 -0800 @@ -0,0 +1,285 @@ +/* + * 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 org.graalvm.compiler.core.common; + +import java.util.AbstractSet; +import java.util.Collection; +import java.util.IdentityHashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; +import java.util.Spliterator; +import java.util.Spliterators; +import java.util.function.Consumer; + +/** + * A map that combines {@link IdentityHashMap} with {@link LinkedHashMap} for the purpose of + * ensuring a deterministic execution order during a capturing compilation. + */ +final class LinkedIdentityHashMap implements Map { + + private final LinkedHashMap, V> map; + + LinkedIdentityHashMap() { + map = new LinkedHashMap<>(); + } + + LinkedIdentityHashMap(Map m) { + map = new LinkedHashMap<>(m.size()); + putAll(m); + } + + 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. + */ + static final class Id { + final T object; + + Id(T object) { + assert object != null; + this.object = object; + } + + @SuppressWarnings("unchecked") + @Override + public boolean equals(Object obj) { + return obj instanceof Id && ((Id) obj).object == object; + } + + @Override + public int hashCode() { + return System.identityHashCode(object); + } + } + + @Override + public int size() { + return map.size(); + } + + @Override + public boolean isEmpty() { + return map.isEmpty(); + } + + @Override + 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); + } + + @Override + public boolean containsValue(Object value) { + return map.containsValue(value); + } + + @Override + public V get(Object key) { + return map.get(id(key)); + } + + @Override + public V put(K key, V value) { + return map.put(id(key), value); + } + + @Override + public V remove(Object key) { + return map.remove(id(key)); + } + + @Override + @SuppressWarnings("unchecked") + public void putAll(Map m) { + if (m == null) { + throw new NullPointerException(); + } + if (m.getClass() == getClass()) { + LinkedIdentityHashMap that = (LinkedIdentityHashMap) m; + map.putAll(that.map); + + } else { + for (K key : m.keySet()) { + map.put(id(key), m.get(key)); + } + } + } + + @Override + 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(); + + @Override + public boolean hasNext() { + return i.hasNext(); + } + + @Override + public K next() { + return i.next().object; + } + + @Override + 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; + } + + @Override + public Spliterator spliterator() { + return Spliterators.spliterator(this, Spliterator.SIZED | Spliterator.ORDERED | Spliterator.DISTINCT); + } + + @Override + public void forEach(Consumer action) { + throw new UnsupportedOperationException(); + } + } + + @Override + public Set keySet() { + return new KeySet(); + } + + @Override + 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(); + + @Override + public boolean hasNext() { + return i.hasNext(); + } + + @Override + public Map.Entry next() { + Map.Entry, V> e = i.next(); + return new Map.Entry() { + + @Override + public K getKey() { + return e.getKey().object; + } + + @Override + public V getValue() { + return e.getValue(); + } + + @Override + public V setValue(V value) { + return e.setValue(value); + } + }; + } + + @Override + public void remove() { + i.remove(); + } + }; + } + + @Override + public boolean contains(Object o) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean remove(Object o) { + throw new UnsupportedOperationException(); + } + + @Override + public Spliterator> spliterator() { + throw new UnsupportedOperationException(); + } + + @Override + public void forEach(Consumer> action) { + throw new UnsupportedOperationException(); + } + } + + @Override + public Set> entrySet() { + return new EntrySet(); + } +}