# HG changeset patch # User Andreas Woess # Date 1442248374 -7200 # Node ID b59d064835806ad1131917e5e8fbfb367cd34372 # Parent 291574f3e498f58429684328c43e0b8def25b604 PropertyMap refactoring diff -r 291574f3e498 -r b59d06483580 truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/ConsListPropertyMap.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/ConsListPropertyMap.java Mon Sep 14 18:32:54 2015 +0200 @@ -0,0 +1,392 @@ +/* + * Copyright (c) 2014, 2015, 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.truffle.object; + +import java.util.*; + +import com.oracle.truffle.api.object.*; + +/** + * Implementation of {@link PropertyMap} as a reverse-order cons (snoc) list. + */ +final class ConsListPropertyMap extends PropertyMap { + private final ConsListPropertyMap car; + private final Property cdr; + private final int size; + + private static final ConsListPropertyMap EMPTY = new ConsListPropertyMap(); + + private ConsListPropertyMap() { + this.car = null; + this.cdr = null; + this.size = 0; + } + + private ConsListPropertyMap(ConsListPropertyMap parent, Property added) { + this.car = Objects.requireNonNull(parent); + this.cdr = added; + this.size = parent.size + 1; + } + + public static ConsListPropertyMap empty() { + return EMPTY; + } + + public int size() { + return size; + } + + public boolean isEmpty() { + return size() == 0; + } + + public boolean containsKey(Object key) { + for (Map.Entry entry : reverseOrderEntrySet()) { + if (entry.getKey().equals(key)) { + return true; + } + } + return false; + } + + public boolean containsValue(Object value) { + for (Map.Entry entry : reverseOrderEntrySet()) { + if (entry.getValue().equals(value)) { + return true; + } + } + return false; + } + + public Property get(Object key) { + for (Map.Entry entry : reverseOrderEntrySet()) { + if (entry.getKey().equals(key)) { + return entry.getValue(); + } + } + return null; + } + + public Set keySet() { + return new AbstractSet() { + @Override + public Iterator iterator() { + return ConsListPropertyMap.this.orderedKeyIterator(); + } + + @Override + public int size() { + return ConsListPropertyMap.this.size(); + } + }; + } + + public Collection values() { + return new AbstractSet() { + @Override + public Iterator iterator() { + return ConsListPropertyMap.this.orderedValueIterator(); + } + + @Override + public int size() { + return ConsListPropertyMap.this.size(); + } + }; + } + + public Set> entrySet() { + return new AbstractSet>() { + @Override + public Iterator> iterator() { + @SuppressWarnings("unchecked") + Map.Entry[] entries = (Map.Entry[]) new Map.Entry[size()]; + Iterator> iterator = reverseOrderEntrySet().iterator(); + for (int pos = size() - 1; pos >= 0; pos--) { + entries[pos] = iterator.next(); + } + return Arrays.asList(entries).iterator(); + } + + @Override + public int size() { + return ConsListPropertyMap.this.size(); + } + }; + } + + public Set> reverseOrderEntrySet() { + return new AbstractSet>() { + @Override + public Iterator> iterator() { + return new Iterator>() { + ConsListPropertyMap current = ConsListPropertyMap.this; + + public Entry next() { + if (hasNext()) { + try { + return new MapEntryImpl(current.cdr); + } finally { + current = current.car; + } + } else { + throw new NoSuchElementException(); + } + } + + public boolean hasNext() { + return current != empty(); + } + + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + + @Override + public int size() { + return ConsListPropertyMap.this.size(); + } + }; + } + + @Override + public Iterator orderedKeyIterator() { + Object[] keys = new Object[size()]; + Iterator> iterator = reverseOrderEntrySet().iterator(); + for (int pos = size() - 1; pos >= 0; pos--) { + keys[pos] = iterator.next().getKey(); + } + return Arrays.asList(keys).iterator(); + } + + @Override + public Iterator reverseOrderedKeyIterator() { + return reverseOrderKeys().iterator(); + } + + public Set reverseOrderKeys() { + return new AbstractSet() { + @Override + public Iterator iterator() { + return new Iterator() { + ConsListPropertyMap current = ConsListPropertyMap.this; + + public Object next() { + if (hasNext()) { + try { + return current.cdr.getKey(); + } finally { + current = current.car; + } + } else { + throw new NoSuchElementException(); + } + } + + public boolean hasNext() { + return current != empty(); + } + + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + + @Override + public int size() { + return ConsListPropertyMap.this.size(); + } + }; + } + + @Override + public Iterator orderedValueIterator() { + Property[] values = new Property[size()]; + Iterator> iterator = reverseOrderEntrySet().iterator(); + for (int pos = size() - 1; pos >= 0; pos--) { + values[pos] = iterator.next().getValue(); + } + return Arrays.asList(values).iterator(); + } + + @Override + public Iterator reverseOrderedValueIterator() { + return reverseOrderValues().iterator(); + } + + public Set reverseOrderValues() { + return new AbstractSet() { + @Override + public Iterator iterator() { + return new Iterator() { + ConsListPropertyMap current = ConsListPropertyMap.this; + + public Property next() { + if (hasNext()) { + try { + return current.cdr; + } finally { + current = current.car; + } + } else { + throw new NoSuchElementException(); + } + } + + public boolean hasNext() { + return current != empty(); + } + + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + + @Override + public int size() { + return ConsListPropertyMap.this.size(); + } + }; + } + + private static final class MapEntryImpl implements Map.Entry { + private final Property backingProperty; + + public MapEntryImpl(Property backingProperty) { + this.backingProperty = backingProperty; + } + + public Object getKey() { + return backingProperty.getKey(); + } + + public Property getValue() { + return backingProperty; + } + + public Property setValue(Property value) { + throw unmodifiableException(); + } + } + + public PropertyMap copyAndPut(Object key, Property value) { + if (!value.getKey().equals(key)) { + throw new IllegalArgumentException("Key must equal extracted key of property."); + } + + return putCopy(value); + } + + public ImmutableMap copyAndRemove(Object key) { + Deque shelve = new ArrayDeque<>(); + ConsListPropertyMap current = this; + while (!current.isEmpty()) { + if (current.getLastProperty().getKey().equals(key)) { + ConsListPropertyMap newMap = current.getParentMap(); + for (Property property : shelve) { + newMap = newMap.putCopy(property); + } + return newMap; + } else { + shelve.push(current.getLastProperty()); + current = current.getParentMap(); + } + } + return this; + } + + @Override + public ConsListPropertyMap putCopy(Property value) { + return new ConsListPropertyMap(this, value); + } + + @Override + public ConsListPropertyMap removeCopy(Property value) { + Deque shelve = new ArrayDeque<>(); + ConsListPropertyMap current = this; + while (!current.isEmpty()) { + if (current.getLastProperty().equals(value)) { + ConsListPropertyMap newMap = current.getParentMap(); + for (Property property : shelve) { + newMap = newMap.putCopy(property); + } + return newMap; + } else { + shelve.push(current.getLastProperty()); + current = current.getParentMap(); + } + } + return this; + } + + @Override + public ConsListPropertyMap replaceCopy(Property oldValue, Property newValue) { + Deque shelve = new ArrayDeque<>(); + ConsListPropertyMap current = this; + while (!current.isEmpty()) { + if (current.getLastProperty().equals(oldValue)) { + ConsListPropertyMap newMap = current.getParentMap(); + newMap = newMap.putCopy(newValue); + for (Property property : shelve) { + newMap = newMap.putCopy(property); + } + return newMap; + } else { + shelve.push(current.getLastProperty()); + current = current.getParentMap(); + } + } + return this; + } + + public ConsListPropertyMap getOwningMap(Property value) { + ConsListPropertyMap current = this; + while (!current.isEmpty()) { + if (current.getLastProperty().equals(value)) { + return current; + } + current = current.getParentMap(); + } + return null; + } + + @Override + public ConsListPropertyMap getParentMap() { + return car; + } + + @Override + public Property getLastProperty() { + return cdr; + } + + @Override + public String toString() { + return values().toString(); + } + +} diff -r 291574f3e498 -r b59d06483580 truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/ImmutableMap.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/ImmutableMap.java Mon Sep 14 18:32:54 2015 +0200 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2015, 2015, 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.truffle.object; + +import java.util.*; + +/** + * An immutable {@link Map}. Does not permit null keys or values. + */ +public interface ImmutableMap extends Map { + + /** + * Creates an immutable copy of this map with the given entry put in the map. + */ + ImmutableMap copyAndPut(final K key, final V value); + + /** + * Creates an immutable copy of this map with the given entry removed from the map. + */ + ImmutableMap copyAndRemove(final K key); + +} diff -r 291574f3e498 -r b59d06483580 truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/PropertyMap.java --- a/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/PropertyMap.java Mon Sep 14 18:07:17 2015 +0200 +++ b/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/PropertyMap.java Mon Sep 14 18:32:54 2015 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, 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 @@ -26,332 +26,54 @@ import com.oracle.truffle.api.object.*; -public final class PropertyMap implements Map { - private final PropertyMap car; - private final Property cdr; - private final int size; - - private static final PropertyMap EMPTY = new PropertyMap(); - - private PropertyMap() { - this.car = null; - this.cdr = null; - this.size = 0; - } - - private PropertyMap(PropertyMap parent, Property added) { - this.car = Objects.requireNonNull(parent); - this.cdr = added; - this.size = parent.size + 1; - } +/** + * Immutable property map. + */ +public abstract class PropertyMap implements ImmutableMap { public static PropertyMap empty() { - return EMPTY; - } - - public int size() { - return size; + return ConsListPropertyMap.empty(); } - public boolean isEmpty() { - return size() == 0; - } + public abstract Iterator orderedKeyIterator(); + + public abstract Iterator reverseOrderedKeyIterator(); - public boolean containsKey(Object key) { - for (Map.Entry entry : reverseOrderEntrySet()) { - if (entry.getKey().equals(key)) { - return true; - } - } - return false; - } + public abstract Iterator orderedValueIterator(); + + public abstract Iterator reverseOrderedValueIterator(); + + public abstract Property getLastProperty(); - public boolean containsValue(Object value) { - for (Map.Entry entry : reverseOrderEntrySet()) { - if (entry.getValue().equals(value)) { - return true; - } - } - return false; - } + public abstract PropertyMap putCopy(final Property element); + + public abstract PropertyMap replaceCopy(final Property oldValue, final Property newValue); - public Property get(Object key) { - for (Map.Entry entry : reverseOrderEntrySet()) { - if (entry.getKey().equals(key)) { - return entry.getValue(); - } - } - return null; - } + public abstract PropertyMap removeCopy(final Property value); - public Property put(Object key, Property value) { + public abstract PropertyMap getParentMap(); + + @Override + public Property put(final Object key, final Property value) { throw unmodifiableException(); } - public Property remove(Object key) { + @Override + public void putAll(final Map m) { throw unmodifiableException(); } - public void putAll(Map m) { + @Override + public Property remove(final Object key) { throw unmodifiableException(); } + @Override public void clear() { throw unmodifiableException(); } - public Set keySet() { - return new AbstractSet() { - @Override - public Iterator iterator() { - Object[] keys = new Object[size()]; - Iterator> iterator = reverseOrderEntrySet().iterator(); - for (int pos = size() - 1; pos >= 0; pos--) { - keys[pos] = iterator.next().getKey(); - } - return Arrays.asList(keys).iterator(); - } - - @Override - public int size() { - return PropertyMap.this.size(); - } - }; - } - - public Collection values() { - return new AbstractSet() { - @Override - public Iterator iterator() { - Property[] values = new Property[size()]; - Iterator> iterator = reverseOrderEntrySet().iterator(); - for (int pos = size() - 1; pos >= 0; pos--) { - values[pos] = iterator.next().getValue(); - } - return Arrays.asList(values).iterator(); - } - - @Override - public int size() { - return PropertyMap.this.size(); - } - }; - } - - public Set> entrySet() { - return new AbstractSet>() { - @Override - public Iterator> iterator() { - @SuppressWarnings("unchecked") - Map.Entry[] entries = (Map.Entry[]) new Map.Entry[size()]; - Iterator> iterator = reverseOrderEntrySet().iterator(); - for (int pos = size() - 1; pos >= 0; pos--) { - entries[pos] = iterator.next(); - } - return Arrays.asList(entries).iterator(); - } - - @Override - public int size() { - return PropertyMap.this.size(); - } - }; - } - - public Set> reverseOrderEntrySet() { - return new AbstractSet>() { - @Override - public Iterator> iterator() { - return new Iterator>() { - PropertyMap current = PropertyMap.this; - - public Entry next() { - if (hasNext()) { - try { - return new MapEntryImpl(current.cdr); - } finally { - current = current.car; - } - } else { - throw new NoSuchElementException(); - } - } - - public boolean hasNext() { - return current != empty(); - } - - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } - - @Override - public int size() { - return PropertyMap.this.size(); - } - }; - } - - public Set reverseOrderKeys() { - return new AbstractSet() { - @Override - public Iterator iterator() { - return new Iterator() { - PropertyMap current = PropertyMap.this; - - public Object next() { - if (hasNext()) { - try { - return current.cdr.getKey(); - } finally { - current = current.car; - } - } else { - throw new NoSuchElementException(); - } - } - - public boolean hasNext() { - return current != empty(); - } - - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } - - @Override - public int size() { - return PropertyMap.this.size(); - } - }; - } - - public Set reverseOrderValues() { - return new AbstractSet() { - @Override - public Iterator iterator() { - return new Iterator() { - PropertyMap current = PropertyMap.this; - - public Property next() { - if (hasNext()) { - try { - return current.cdr; - } finally { - current = current.car; - } - } else { - throw new NoSuchElementException(); - } - } - - public boolean hasNext() { - return current != empty(); - } - - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } - - @Override - public int size() { - return PropertyMap.this.size(); - } - }; - } - - private static final class MapEntryImpl implements Map.Entry { - private final Property backingProperty; - - public MapEntryImpl(Property backingProperty) { - this.backingProperty = backingProperty; - } - - public Object getKey() { - return backingProperty.getKey(); - } - - public Property getValue() { - return backingProperty; - } - - public Property setValue(Property value) { - throw unmodifiableException(); - } - } - - private static UnsupportedOperationException unmodifiableException() { - throw new UnsupportedOperationException("unmodifiable"); - } - - public PropertyMap putCopy(Property value) { - return new PropertyMap(this, value); - } - - public PropertyMap removeCopy(Property value) { - Deque shelve = new ArrayDeque<>(); - PropertyMap current = this; - while (!current.isEmpty()) { - if (current.getLastProperty().equals(value)) { - PropertyMap newMap = current.getParentMap(); - for (Property property : shelve) { - newMap = newMap.putCopy(property); - } - return newMap; - } else { - shelve.push(current.getLastProperty()); - current = current.getParentMap(); - } - } - return this; - } - - public PropertyMap replaceCopy(Property oldValue, Property newValue) { - Deque shelve = new ArrayDeque<>(); - PropertyMap current = this; - while (!current.isEmpty()) { - if (current.getLastProperty().equals(oldValue)) { - PropertyMap newMap = current.getParentMap(); - newMap = newMap.putCopy(newValue); - for (Property property : shelve) { - newMap = newMap.putCopy(property); - } - return newMap; - } else { - shelve.push(current.getLastProperty()); - current = current.getParentMap(); - } - } - return this; - } - - public PropertyMap getOwningMap(Property value) { - PropertyMap current = this; - while (!current.isEmpty()) { - if (current.getLastProperty().equals(value)) { - return current; - } - current = current.getParentMap(); - } - return null; - } - - PropertyMap getParentMap() { - return car; - } - - public Property getLastProperty() { - return cdr; - } - - @Override - public String toString() { - return values().toString(); + protected static RuntimeException unmodifiableException() { + throw new UnsupportedOperationException(); } } diff -r 291574f3e498 -r b59d06483580 truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/ShapeImpl.java --- a/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/ShapeImpl.java Mon Sep 14 18:07:17 2015 +0200 +++ b/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/ShapeImpl.java Mon Sep 14 18:32:54 2015 +0200 @@ -99,6 +99,7 @@ * * @param parent predecessor shape * @param transitionFromParent direct transition from parent shape + * * @see #ShapeImpl(Layout, ShapeImpl, ObjectType, Object, PropertyMap, Transition, * BaseAllocator, int) */ @@ -109,7 +110,7 @@ this.propertyMap = Objects.requireNonNull(propertyMap); this.root = parent != null ? parent.getRoot() : this; this.parent = parent; - this.transitionFromParent = transitionFromParent; + this.objectArraySize = objectArraySize; this.objectArrayCapacity = capacityFromSize(objectArraySize); this.objectFieldSize = objectFieldSize; @@ -129,11 +130,11 @@ this.validAssumption = createValidAssumption(); this.id = id; - shapeCount.inc(); - + this.transitionFromParent = transitionFromParent; this.sharedData = sharedData; this.extraData = objectType.createShapeData(this); + shapeCount.inc(); debugRegisterShape(this); } @@ -150,7 +151,13 @@ } private static int makePropertyCount(ShapeImpl parent, PropertyMap propertyMap) { - return parent.propertyCount + ((propertyMap.size() > parent.propertyMap.size() && !propertyMap.getLastProperty().isHidden() && !propertyMap.getLastProperty().isShadow()) ? 1 : 0); + if (propertyMap.size() > parent.propertyMap.size()) { + Property lastProperty = propertyMap.getLastProperty(); + if (!lastProperty.isHidden() && !lastProperty.isShadow()) { + return parent.propertyCount + 1; + } + } + return parent.propertyCount; } @Override @@ -432,7 +439,9 @@ @Override public final List getPropertyList(Pred filter) { LinkedList props = new LinkedList<>(); - next: for (Property currentProperty : this.propertyMap.reverseOrderValues()) { + next: for (Iterator it = this.propertyMap.reverseOrderedValueIterator(); it.hasNext();) { + Property currentProperty = it.next(); + if (!currentProperty.isHidden() && filter.test(currentProperty)) { if (currentProperty.getLocation() instanceof DeclaredLocation) { for (Iterator iter = props.iterator(); iter.hasNext();) { @@ -464,7 +473,8 @@ @Override public final List getPropertyListInternal(boolean ascending) { LinkedList props = new LinkedList<>(); - for (Property current : this.propertyMap.reverseOrderValues()) { + for (Iterator it = this.propertyMap.reverseOrderedValueIterator(); it.hasNext();) { + Property current = it.next(); if (ascending) { props.addFirst(current); } else { @@ -483,7 +493,8 @@ @Override public final List getKeyList(Pred filter) { LinkedList keys = new LinkedList<>(); - for (Property currentProperty : this.propertyMap.reverseOrderValues()) { + for (Iterator it = this.propertyMap.reverseOrderedValueIterator(); it.hasNext();) { + Property currentProperty = it.next(); if (!currentProperty.isHidden() && filter.test(currentProperty) && !currentProperty.isShadow()) { keys.addFirst(currentProperty.getKey()); } @@ -569,7 +580,7 @@ } sb.append("{"); - for (Iterator iterator = propertyMap.reverseOrderValues().iterator(); iterator.hasNext();) { + for (Iterator iterator = propertyMap.reverseOrderedValueIterator(); iterator.hasNext();) { Property p = iterator.next(); sb.append(p); if (iterator.hasNext()) {