changeset 22153:b59d06483580

PropertyMap refactoring
author Andreas Woess <andreas.woess@oracle.com>
date Mon, 14 Sep 2015 18:32:54 +0200
parents 291574f3e498
children cc195dd45121
files truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/ConsListPropertyMap.java truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/ImmutableMap.java truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/PropertyMap.java truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/ShapeImpl.java
diffstat 4 files changed, 482 insertions(+), 315 deletions(-) [+]
line wrap: on
line diff
--- /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<Object, Property> entry : reverseOrderEntrySet()) {
+            if (entry.getKey().equals(key)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public boolean containsValue(Object value) {
+        for (Map.Entry<Object, Property> entry : reverseOrderEntrySet()) {
+            if (entry.getValue().equals(value)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public Property get(Object key) {
+        for (Map.Entry<Object, Property> entry : reverseOrderEntrySet()) {
+            if (entry.getKey().equals(key)) {
+                return entry.getValue();
+            }
+        }
+        return null;
+    }
+
+    public Set<Object> keySet() {
+        return new AbstractSet<Object>() {
+            @Override
+            public Iterator<Object> iterator() {
+                return ConsListPropertyMap.this.orderedKeyIterator();
+            }
+
+            @Override
+            public int size() {
+                return ConsListPropertyMap.this.size();
+            }
+        };
+    }
+
+    public Collection<Property> values() {
+        return new AbstractSet<Property>() {
+            @Override
+            public Iterator<Property> iterator() {
+                return ConsListPropertyMap.this.orderedValueIterator();
+            }
+
+            @Override
+            public int size() {
+                return ConsListPropertyMap.this.size();
+            }
+        };
+    }
+
+    public Set<Map.Entry<Object, Property>> entrySet() {
+        return new AbstractSet<Map.Entry<Object, Property>>() {
+            @Override
+            public Iterator<Map.Entry<Object, Property>> iterator() {
+                @SuppressWarnings("unchecked")
+                Map.Entry<Object, Property>[] entries = (Map.Entry<Object, Property>[]) new Map.Entry<?, ?>[size()];
+                Iterator<Map.Entry<Object, Property>> 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<Map.Entry<Object, Property>> reverseOrderEntrySet() {
+        return new AbstractSet<Map.Entry<Object, Property>>() {
+            @Override
+            public Iterator<Map.Entry<Object, Property>> iterator() {
+                return new Iterator<Map.Entry<Object, Property>>() {
+                    ConsListPropertyMap current = ConsListPropertyMap.this;
+
+                    public Entry<Object, Property> 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<Object> orderedKeyIterator() {
+        Object[] keys = new Object[size()];
+        Iterator<Map.Entry<Object, Property>> iterator = reverseOrderEntrySet().iterator();
+        for (int pos = size() - 1; pos >= 0; pos--) {
+            keys[pos] = iterator.next().getKey();
+        }
+        return Arrays.asList(keys).iterator();
+    }
+
+    @Override
+    public Iterator<Object> reverseOrderedKeyIterator() {
+        return reverseOrderKeys().iterator();
+    }
+
+    public Set<Object> reverseOrderKeys() {
+        return new AbstractSet<Object>() {
+            @Override
+            public Iterator<Object> iterator() {
+                return new Iterator<Object>() {
+                    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<Property> orderedValueIterator() {
+        Property[] values = new Property[size()];
+        Iterator<Map.Entry<Object, Property>> iterator = reverseOrderEntrySet().iterator();
+        for (int pos = size() - 1; pos >= 0; pos--) {
+            values[pos] = iterator.next().getValue();
+        }
+        return Arrays.asList(values).iterator();
+    }
+
+    @Override
+    public Iterator<Property> reverseOrderedValueIterator() {
+        return reverseOrderValues().iterator();
+    }
+
+    public Set<Property> reverseOrderValues() {
+        return new AbstractSet<Property>() {
+            @Override
+            public Iterator<Property> iterator() {
+                return new Iterator<Property>() {
+                    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<Object, Property> {
+        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<Object, Property> copyAndRemove(Object key) {
+        Deque<Property> 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<Property> 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<Property> 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();
+    }
+
+}
--- /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<K, V> extends Map<K, V> {
+
+    /**
+     * Creates an immutable copy of this map with the given entry put in the map.
+     */
+    ImmutableMap<K, V> copyAndPut(final K key, final V value);
+
+    /**
+     * Creates an immutable copy of this map with the given entry removed from the map.
+     */
+    ImmutableMap<K, V> copyAndRemove(final K key);
+
+}
--- 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<Object, Property> {
-    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<Object, Property> {
 
     public static PropertyMap empty() {
-        return EMPTY;
-    }
-
-    public int size() {
-        return size;
+        return ConsListPropertyMap.empty();
     }
 
-    public boolean isEmpty() {
-        return size() == 0;
-    }
+    public abstract Iterator<Object> orderedKeyIterator();
+
+    public abstract Iterator<Object> reverseOrderedKeyIterator();
 
-    public boolean containsKey(Object key) {
-        for (Map.Entry<Object, Property> entry : reverseOrderEntrySet()) {
-            if (entry.getKey().equals(key)) {
-                return true;
-            }
-        }
-        return false;
-    }
+    public abstract Iterator<Property> orderedValueIterator();
+
+    public abstract Iterator<Property> reverseOrderedValueIterator();
+
+    public abstract Property getLastProperty();
 
-    public boolean containsValue(Object value) {
-        for (Map.Entry<Object, Property> 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<Object, Property> 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<? extends Object, ? extends Property> m) {
         throw unmodifiableException();
     }
 
-    public void putAll(Map<? extends Object, ? extends Property> m) {
+    @Override
+    public Property remove(final Object key) {
         throw unmodifiableException();
     }
 
+    @Override
     public void clear() {
         throw unmodifiableException();
     }
 
-    public Set<Object> keySet() {
-        return new AbstractSet<Object>() {
-            @Override
-            public Iterator<Object> iterator() {
-                Object[] keys = new Object[size()];
-                Iterator<Map.Entry<Object, Property>> 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<Property> values() {
-        return new AbstractSet<Property>() {
-            @Override
-            public Iterator<Property> iterator() {
-                Property[] values = new Property[size()];
-                Iterator<Map.Entry<Object, Property>> 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<Map.Entry<Object, Property>> entrySet() {
-        return new AbstractSet<Map.Entry<Object, Property>>() {
-            @Override
-            public Iterator<Map.Entry<Object, Property>> iterator() {
-                @SuppressWarnings("unchecked")
-                Map.Entry<Object, Property>[] entries = (Map.Entry<Object, Property>[]) new Map.Entry<?, ?>[size()];
-                Iterator<Map.Entry<Object, Property>> 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<Map.Entry<Object, Property>> reverseOrderEntrySet() {
-        return new AbstractSet<Map.Entry<Object, Property>>() {
-            @Override
-            public Iterator<Map.Entry<Object, Property>> iterator() {
-                return new Iterator<Map.Entry<Object, Property>>() {
-                    PropertyMap current = PropertyMap.this;
-
-                    public Entry<Object, Property> 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<Object> reverseOrderKeys() {
-        return new AbstractSet<Object>() {
-            @Override
-            public Iterator<Object> iterator() {
-                return new Iterator<Object>() {
-                    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<Property> reverseOrderValues() {
-        return new AbstractSet<Property>() {
-            @Override
-            public Iterator<Property> iterator() {
-                return new Iterator<Property>() {
-                    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<Object, Property> {
-        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<Property> 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<Property> 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();
     }
 }
--- 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<Property> getPropertyList(Pred<Property> filter) {
         LinkedList<Property> props = new LinkedList<>();
-        next: for (Property currentProperty : this.propertyMap.reverseOrderValues()) {
+        next: for (Iterator<Property> it = this.propertyMap.reverseOrderedValueIterator(); it.hasNext();) {
+            Property currentProperty = it.next();
+
             if (!currentProperty.isHidden() && filter.test(currentProperty)) {
                 if (currentProperty.getLocation() instanceof DeclaredLocation) {
                     for (Iterator<Property> iter = props.iterator(); iter.hasNext();) {
@@ -464,7 +473,8 @@
     @Override
     public final List<Property> getPropertyListInternal(boolean ascending) {
         LinkedList<Property> props = new LinkedList<>();
-        for (Property current : this.propertyMap.reverseOrderValues()) {
+        for (Iterator<Property> it = this.propertyMap.reverseOrderedValueIterator(); it.hasNext();) {
+            Property current = it.next();
             if (ascending) {
                 props.addFirst(current);
             } else {
@@ -483,7 +493,8 @@
     @Override
     public final List<Object> getKeyList(Pred<Property> filter) {
         LinkedList<Object> keys = new LinkedList<>();
-        for (Property currentProperty : this.propertyMap.reverseOrderValues()) {
+        for (Iterator<Property> 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<Property> iterator = propertyMap.reverseOrderValues().iterator(); iterator.hasNext();) {
+        for (Iterator<Property> iterator = propertyMap.reverseOrderedValueIterator(); iterator.hasNext();) {
             Property p = iterator.next();
             sb.append(p);
             if (iterator.hasNext()) {