/*
 * Copyright (c) 2010, 2013, 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.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * 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 jdk.nashorn.internal.runtime;

import static jdk.nashorn.internal.runtime.PropertyHashMap.EMPTY_HASHMAP;
import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.getArrayIndex;
import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.invoke.SwitchPoint;
import java.lang.ref.Reference;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.WeakHashMap;
import java.util.concurrent.atomic.LongAdder;
import jdk.nashorn.internal.runtime.options.Options;
import jdk.nashorn.internal.scripts.JO;

/**
 * Map of object properties. The PropertyMap is the "template" for JavaScript object
 * layouts. It contains a map with prototype names as keys and {@link Property} instances
 * as values. A PropertyMap is typically passed to the {@link ScriptObject} constructor
 * to form the seed map for the ScriptObject.
 * <p>
 * All property maps are immutable. If a property is added, modified or removed, the mutator
 * will return a new map.
 */
public class PropertyMap implements Iterable<Object>, Serializable {
    private static final int INITIAL_SOFT_REFERENCE_DERIVATION_LIMIT =
            Math.max(0, Options.getIntProperty("nashorn.propertyMap.softReferenceDerivationLimit", 32));

    /** Used for non extensible PropertyMaps, negative logic as the normal case is extensible. See {@link ScriptObject#preventExtensions()} */
    private static final int NOT_EXTENSIBLE         = 0b0000_0001;
    /** Does this map contain valid array keys? */
    private static final int CONTAINS_ARRAY_KEYS    = 0b0000_0010;

    /** Map status flags. */
    private final int flags;

    /** Map of properties. */
    private transient PropertyHashMap properties;

    /** Number of fields in use. */
    private final int fieldCount;

    /** Number of fields available. */
    private final int fieldMaximum;

    /** Length of spill in use. */
    private final int spillLength;

    /** Structure class name */
    private final String className;

    /**
     * Countdown of number of times this property map has been derived from another property map. When it
     * reaches zero, the property map will start using weak references instead of soft references to hold on
     * to its history elements.
     */
    private final int softReferenceDerivationLimit;

    /** A reference to the expected shared prototype property map. If this is set this
     * property map should only be used if it the same as the actual prototype map. */
    private transient SharedPropertyMap sharedProtoMap;

    /** {@link SwitchPoint}s for gets on inherited properties. */
    private transient HashMap<String, SwitchPoint> protoSwitches;

    /** History of maps, used to limit map duplication. */
    private transient WeakHashMap<Property, Reference<PropertyMap>> history;

    /** History of prototypes, used to limit map duplication. */
    private transient WeakHashMap<ScriptObject, SoftReference<PropertyMap>> protoHistory;

    /** property listeners */
    private transient PropertyListeners listeners;

    private transient BitSet freeSlots;

    private static final long serialVersionUID = -7041836752008732533L;

    /**
     * Constructs a new property map.
     *
     * @param properties   A {@link PropertyHashMap} with initial contents.
     * @param fieldCount   Number of fields in use.
     * @param fieldMaximum Number of fields available.
     * @param spillLength  Number of spill slots used.
     */
    private PropertyMap(final PropertyHashMap properties, final int flags, final String className,
                        final int fieldCount, final int fieldMaximum, final int spillLength) {
        this.properties   = properties;
        this.className    = className;
        this.fieldCount   = fieldCount;
        this.fieldMaximum = fieldMaximum;
        this.spillLength  = spillLength;
        this.flags        = flags;
        this.softReferenceDerivationLimit = INITIAL_SOFT_REFERENCE_DERIVATION_LIMIT;

        if (Context.DEBUG) {
            count.increment();
        }
    }

    /**
     * Constructs a clone of {@code propertyMap} with changed properties, flags, or boundaries.
     *
     * @param propertyMap Existing property map.
     * @param properties  A {@link PropertyHashMap} with a new set of properties.
     */
    private PropertyMap(final PropertyMap propertyMap, final PropertyHashMap properties, final int flags, final int fieldCount, final int spillLength, final int softReferenceDerivationLimit) {
        this.properties   = properties;
        this.flags        = flags;
        this.spillLength  = spillLength;
        this.fieldCount   = fieldCount;
        this.fieldMaximum = propertyMap.fieldMaximum;
        this.className    = propertyMap.className;
        // We inherit the parent property listeners instance. It will be cloned when a new listener is added.
        this.listeners    = propertyMap.listeners;
        this.freeSlots    = propertyMap.freeSlots;
        this.sharedProtoMap = propertyMap.sharedProtoMap;
        this.softReferenceDerivationLimit = softReferenceDerivationLimit;

        if (Context.DEBUG) {
            count.increment();
            clonedCount.increment();
        }
    }

    /**
     * Constructs an exact clone of {@code propertyMap}.
     *
     * @param propertyMap Existing property map.
      */
    protected PropertyMap(final PropertyMap propertyMap) {
        this(propertyMap, propertyMap.properties, propertyMap.flags, propertyMap.fieldCount, propertyMap.spillLength, propertyMap.softReferenceDerivationLimit);
    }

    private void writeObject(final ObjectOutputStream out) throws IOException {
        out.defaultWriteObject();
        out.writeObject(properties.getProperties());
    }

    private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
        in.defaultReadObject();

        final Property[] props = (Property[]) in.readObject();
        this.properties = EMPTY_HASHMAP.immutableAdd(props);

        assert className != null;
        final Class<?> structure = Context.forStructureClass(className);
        for (final Property prop : props) {
            prop.initMethodHandles(structure);
        }
    }

    /**
     * Public property map allocator.
     *
     * <p>It is the caller's responsibility to make sure that {@code properties} does not contain
     * properties with keys that are valid array indices.</p>
     *
     * @param properties   Collection of initial properties.
     * @param className    class name
     * @param fieldCount   Number of fields in use.
     * @param fieldMaximum Number of fields available.
     * @param spillLength  Number of used spill slots.
     * @return New {@link PropertyMap}.
     */
    public static PropertyMap newMap(final Collection<Property> properties, final String className, final int fieldCount, final int fieldMaximum,  final int spillLength) {
        final PropertyHashMap newProperties = EMPTY_HASHMAP.immutableAdd(properties);
        return new PropertyMap(newProperties, 0, className, fieldCount, fieldMaximum, spillLength);
    }

    /**
     * Public property map allocator. Used by nasgen generated code.
     *
     * <p>It is the caller's responsibility to make sure that {@code properties} does not contain
     * properties with keys that are valid array indices.</p>
     *
     * @param properties Collection of initial properties.
     * @return New {@link PropertyMap}.
     */
    public static PropertyMap newMap(final Collection<Property> properties) {
        return properties == null || properties.isEmpty()? newMap() : newMap(properties, JO.class.getName(), 0, 0, 0);
    }

    /**
     * Return a sharable empty map for the given object class.
     * @param clazz the base object class
     * @return New empty {@link PropertyMap}.
     */
    public static PropertyMap newMap(final Class<? extends ScriptObject> clazz) {
        return new PropertyMap(EMPTY_HASHMAP, 0, clazz.getName(), 0, 0, 0);
    }

    /**
     * Return a sharable empty map.
     *
     * @return New empty {@link PropertyMap}.
     */
    public static PropertyMap newMap() {
        return newMap(JO.class);
    }

    /**
     * Return number of properties in the map.
     *
     * @return Number of properties.
     */
    public int size() {
        return properties.size();
    }

    /**
     * Get the number of listeners of this map
     *
     * @return the number of listeners
     */
    public int getListenerCount() {
        return listeners == null ? 0 : listeners.getListenerCount();
    }

    /**
     * Add {@code listenerMap} as a listener to this property map for the given {@code key}.
     *
     * @param key the property name
     * @param listenerMap the listener map
     */
    public void addListener(final String key, final PropertyMap listenerMap) {
        if (listenerMap != this) {
            // We need to clone listener instance when adding a new listener since we share
            // the listeners instance with our parent maps that don't need to see the new listener.
            listeners = PropertyListeners.addListener(listeners, key, listenerMap);
        }
    }

    /**
     * A new property is being added.
     *
     * @param property The new Property added.
     * @param isSelf was the property added to this map?
     */
    public void propertyAdded(final Property property, final boolean isSelf) {
        if (!isSelf) {
            invalidateProtoSwitchPoint(property.getKey());
        }
        if (listeners != null) {
            listeners.propertyAdded(property);
        }
    }

    /**
     * An existing property is being deleted.
     *
     * @param property The property being deleted.
     * @param isSelf was the property deleted from this map?
     */
    public void propertyDeleted(final Property property, final boolean isSelf) {
        if (!isSelf) {
            invalidateProtoSwitchPoint(property.getKey());
        }
        if (listeners != null) {
            listeners.propertyDeleted(property);
        }
    }

    /**
     * An existing property is being redefined.
     *
     * @param oldProperty The old property
     * @param newProperty The new property
     * @param isSelf was the property modified on this map?
     */
    public void propertyModified(final Property oldProperty, final Property newProperty, final boolean isSelf) {
        if (!isSelf) {
            invalidateProtoSwitchPoint(oldProperty.getKey());
        }
        if (listeners != null) {
            listeners.propertyModified(oldProperty, newProperty);
        }
    }

    /**
     * The prototype of an object associated with this {@link PropertyMap} is changed.
     *
     * @param isSelf was the prototype changed on the object using this map?
     */
    public void protoChanged(final boolean isSelf) {
        if (!isSelf) {
            invalidateAllProtoSwitchPoints();
        } else if (sharedProtoMap != null) {
            sharedProtoMap.invalidateSwitchPoint();
        }
        if (listeners != null) {
            listeners.protoChanged();
        }
    }

    /**
     * Return a SwitchPoint used to track changes of a property in a prototype.
     *
     * @param key Property key.
     * @return A shared {@link SwitchPoint} for the property.
     */
    public synchronized SwitchPoint getSwitchPoint(final String key) {
        if (protoSwitches == null) {
            protoSwitches = new HashMap<>();
        }

        SwitchPoint switchPoint = protoSwitches.get(key);
        if (switchPoint == null) {
            switchPoint = new SwitchPoint();
            protoSwitches.put(key, switchPoint);
        }

        return switchPoint;
    }

    /**
     * Indicate that a prototype property has changed.
     *
     * @param key {@link Property} key to invalidate.
     */
    synchronized void invalidateProtoSwitchPoint(final String key) {
        if (protoSwitches != null) {
            final SwitchPoint sp = protoSwitches.get(key);
            if (sp != null) {
                protoSwitches.remove(key);
                if (Context.DEBUG) {
                    protoInvalidations.increment();
                }
                SwitchPoint.invalidateAll(new SwitchPoint[]{sp});
            }
        }
    }

    /**
     * Indicate that proto itself has changed in hierarchy somewhere.
     */
    synchronized void invalidateAllProtoSwitchPoints() {
        if (protoSwitches != null) {
            final int size = protoSwitches.size();
            if (size > 0) {
                if (Context.DEBUG) {
                    protoInvalidations.add(size);
                }
                SwitchPoint.invalidateAll(protoSwitches.values().toArray(new SwitchPoint[size]));
                protoSwitches.clear();
            }
        }
    }

    /**
     * Add a property to the map, re-binding its getters and setters,
     * if available, to a given receiver. This is typically the global scope. See
     * {@link ScriptObject#addBoundProperties(ScriptObject)}
     *
     * @param property {@link Property} being added.
     * @param bindTo   Object to bind to.
     *
     * @return New {@link PropertyMap} with {@link Property} added.
     */
    PropertyMap addPropertyBind(final AccessorProperty property, final Object bindTo) {
        // We must not store bound property in the history as bound properties can't be reused.
        return addPropertyNoHistory(new AccessorProperty(property, bindTo));
    }

    // Get a logical slot index for a property, with spill slot 0 starting at fieldMaximum.
    private int logicalSlotIndex(final Property property) {
        final int slot = property.getSlot();
        if (slot < 0) {
            return -1;
        }
        return property.isSpill() ? slot + fieldMaximum : slot;
    }

    private int newSpillLength(final Property newProperty) {
        return newProperty.isSpill() ? Math.max(spillLength, newProperty.getSlot() + 1) : spillLength;
    }

    private int newFieldCount(final Property newProperty) {
        return !newProperty.isSpill() ? Math.max(fieldCount, newProperty.getSlot() + 1) : fieldCount;
    }

    private int newFlags(final Property newProperty) {
        return isValidArrayIndex(getArrayIndex(newProperty.getKey())) ? flags | CONTAINS_ARRAY_KEYS : flags;
    }

    // Update the free slots bitmap for a property that has been deleted and/or added. This method is not synchronized
    // as it is always invoked on a newly created instance.
    private void updateFreeSlots(final Property oldProperty, final Property newProperty) {
        // Free slots bitset is possibly shared with parent map, so we must clone it before making modifications.
        boolean freeSlotsCloned = false;
        if (oldProperty != null) {
            final int slotIndex = logicalSlotIndex(oldProperty);
            if (slotIndex >= 0) {
                final BitSet newFreeSlots = freeSlots == null ? new BitSet() : (BitSet)freeSlots.clone();
                assert !newFreeSlots.get(slotIndex);
                newFreeSlots.set(slotIndex);
                freeSlots = newFreeSlots;
                freeSlotsCloned = true;
            }
        }
        if (freeSlots != null && newProperty != null) {
            final int slotIndex = logicalSlotIndex(newProperty);
            if (slotIndex > -1 && freeSlots.get(slotIndex)) {
                final BitSet newFreeSlots = freeSlotsCloned ? freeSlots : ((BitSet)freeSlots.clone());
                newFreeSlots.clear(slotIndex);
                freeSlots = newFreeSlots.isEmpty() ? null : newFreeSlots;
            }
        }
    }

    /**
     * Add a property to the map without adding it to the history. This should be used for properties that
     * can't be shared such as bound properties, or properties that are expected to be added only once.
     *
     * @param property {@link Property} being added.
     * @return New {@link PropertyMap} with {@link Property} added.
     */
    public final PropertyMap addPropertyNoHistory(final Property property) {
        propertyAdded(property, true);
        return addPropertyInternal(property);
    }

    /**
     * Add a property to the map.  Cloning or using an existing map if available.
     *
     * @param property {@link Property} being added.
     *
     * @return New {@link PropertyMap} with {@link Property} added.
     */
    public final synchronized PropertyMap addProperty(final Property property) {
        propertyAdded(property, true);
        PropertyMap newMap = checkHistory(property);

        if (newMap == null) {
            newMap = addPropertyInternal(property);
            addToHistory(property, newMap);
        }

        return newMap;
    }

    private PropertyMap deriveMap(final PropertyHashMap newProperties, final int newFlags, final int newFieldCount, final int newSpillLength) {
        return new PropertyMap(this, newProperties, newFlags, newFieldCount, newSpillLength, softReferenceDerivationLimit == 0 ? 0 : softReferenceDerivationLimit - 1);
    }

    private PropertyMap addPropertyInternal(final Property property) {
        final PropertyHashMap newProperties = properties.immutableAdd(property);
        final PropertyMap newMap = deriveMap(newProperties, newFlags(property), newFieldCount(property), newSpillLength(property));
        newMap.updateFreeSlots(null, property);
        return newMap;
    }

    /**
     * Remove a property from a map. Cloning or using an existing map if available.
     *
     * @param property {@link Property} being removed.
     *
     * @return New {@link PropertyMap} with {@link Property} removed or {@code null} if not found.
     */
    public final synchronized PropertyMap deleteProperty(final Property property) {
        propertyDeleted(property, true);
        PropertyMap newMap = checkHistory(property);
        final String key = property.getKey();

        if (newMap == null && properties.containsKey(key)) {
            final PropertyHashMap newProperties = properties.immutableRemove(key);
            final boolean isSpill = property.isSpill();
            final int slot = property.getSlot();
            // If deleted property was last field or spill slot we can make it reusable by reducing field/slot count.
            // Otherwise mark it as free in free slots bitset.
            if (isSpill && slot >= 0 && slot == spillLength - 1) {
                newMap = deriveMap(newProperties, flags, fieldCount, spillLength - 1);
                newMap.freeSlots = freeSlots;
            } else if (!isSpill && slot >= 0 && slot == fieldCount - 1) {
                newMap = deriveMap(newProperties, flags, fieldCount - 1, spillLength);
                newMap.freeSlots = freeSlots;
            } else {
                newMap = deriveMap(newProperties, flags, fieldCount, spillLength);
                newMap.updateFreeSlots(property, null);
            }
            addToHistory(property, newMap);
        }

        return newMap;
    }

    /**
     * Replace an existing property with a new one.
     *
     * @param oldProperty Property to replace.
     * @param newProperty New {@link Property}.
     *
     * @return New {@link PropertyMap} with {@link Property} replaced.
     */
    public final PropertyMap replaceProperty(final Property oldProperty, final Property newProperty) {
        propertyModified(oldProperty, newProperty, true);
        /*
         * See ScriptObject.modifyProperty and ScriptObject.setUserAccessors methods.
         *
         * This replaceProperty method is called only for the following three cases:
         *
         *   1. To change flags OR TYPE of an old (cloned) property. We use the same spill slots.
         *   2. To change one UserAccessor property with another - user getter or setter changed via
         *      Object.defineProperty function. Again, same spill slots are re-used.
         *   3. Via ScriptObject.setUserAccessors method to set user getter and setter functions
         *      replacing the dummy AccessorProperty with null method handles (added during map init).
         *
         * In case (1) and case(2), the property type of old and new property is same. For case (3),
         * the old property is an AccessorProperty and the new one is a UserAccessorProperty property.
         */

        final boolean sameType = oldProperty.getClass() == newProperty.getClass();
        assert sameType ||
                oldProperty instanceof AccessorProperty &&
                newProperty instanceof UserAccessorProperty :
            "arbitrary replaceProperty attempted " + sameType + " oldProperty=" + oldProperty.getClass() + " newProperty=" + newProperty.getClass() + " [" + oldProperty.getLocalType() + " => " + newProperty.getLocalType() + "]";

        /*
         * spillLength remains same in case (1) and (2) because of slot reuse. Only for case (3), we need
         * to add spill count of the newly added UserAccessorProperty property.
         */
        final int newSpillLength = sameType ? spillLength : Math.max(spillLength, newProperty.getSlot() + 1);

        // Add replaces existing property.
        final PropertyHashMap newProperties = properties.immutableReplace(oldProperty, newProperty);
        final PropertyMap newMap = deriveMap(newProperties, flags, fieldCount, newSpillLength);

        if (!sameType) {
            newMap.updateFreeSlots(oldProperty, newProperty);
        }
        return newMap;
    }

    /**
     * Make a new UserAccessorProperty property. getter and setter functions are stored in
     * this ScriptObject and slot values are used in property object. Note that slots
     * are assigned speculatively and should be added to map before adding other
     * properties.
     *
     * @param key the property name
     * @param propertyFlags attribute flags of the property
     * @return the newly created UserAccessorProperty
     */
    public final UserAccessorProperty newUserAccessors(final String key, final int propertyFlags) {
        return new UserAccessorProperty(key, propertyFlags, getFreeSpillSlot());
    }

    /**
     * Find a property in the map.
     *
     * @param key Key to search for.
     *
     * @return {@link Property} matching key.
     */
    public final Property findProperty(final String key) {
        return properties.find(key);
    }

    /**
     * Adds all map properties from another map.
     *
     * @param other The source of properties.
     *
     * @return New {@link PropertyMap} with added properties.
     */
    public final PropertyMap addAll(final PropertyMap other) {
        assert this != other : "adding property map to itself";
        final Property[] otherProperties = other.properties.getProperties();
        final PropertyHashMap newProperties = properties.immutableAdd(otherProperties);

        final PropertyMap newMap = deriveMap(newProperties, flags, fieldCount, spillLength);
        for (final Property property : otherProperties) {
            // This method is only safe to use with non-slotted, native getter/setter properties
            assert property.getSlot() == -1;
            assert !(isValidArrayIndex(getArrayIndex(property.getKey())));
        }

        return newMap;
    }

    /**
     * Return an array of all properties.
     *
     * @return Properties as an array.
     */
    public final Property[] getProperties() {
        return properties.getProperties();
    }

    /**
     * Return the name of the class of objects using this property map.
     *
     * @return class name of owner objects.
     */
    public final String getClassName() {
        return className;
    }

    /**
     * Prevents the map from having additional properties.
     *
     * @return New map with {@link #NOT_EXTENSIBLE} flag set.
     */
    PropertyMap preventExtensions() {
        return deriveMap(properties, flags | NOT_EXTENSIBLE, fieldCount, spillLength);
    }

    /**
     * Prevents properties in map from being modified.
     *
     * @return New map with {@link #NOT_EXTENSIBLE} flag set and properties with
     * {@link Property#NOT_CONFIGURABLE} set.
     */
    PropertyMap seal() {
        PropertyHashMap newProperties = EMPTY_HASHMAP;

        for (final Property oldProperty :  properties.getProperties()) {
            newProperties = newProperties.immutableAdd(oldProperty.addFlags(Property.NOT_CONFIGURABLE));
        }

        return deriveMap(newProperties, flags | NOT_EXTENSIBLE, fieldCount, spillLength);
    }

    /**
     * Prevents properties in map from being modified or written to.
     *
     * @return New map with {@link #NOT_EXTENSIBLE} flag set and properties with
     * {@link Property#NOT_CONFIGURABLE} and {@link Property#NOT_WRITABLE} set.
     */
    PropertyMap freeze() {
        PropertyHashMap newProperties = EMPTY_HASHMAP;

        for (final Property oldProperty : properties.getProperties()) {
            int propertyFlags = Property.NOT_CONFIGURABLE;

            if (!(oldProperty instanceof UserAccessorProperty)) {
                propertyFlags |= Property.NOT_WRITABLE;
            }

            newProperties = newProperties.immutableAdd(oldProperty.addFlags(propertyFlags));
        }

        return deriveMap(newProperties, flags | NOT_EXTENSIBLE, fieldCount, spillLength);
    }

    /**
     * Check for any configurable properties.
     *
     * @return {@code true} if any configurable.
     */
    private boolean anyConfigurable() {
        for (final Property property : properties.getProperties()) {
            if (property.isConfigurable()) {
               return true;
            }
        }

        return false;
    }

    /**
     * Check if all properties are frozen.
     *
     * @return {@code true} if all are frozen.
     */
    private boolean allFrozen() {
        for (final Property property : properties.getProperties()) {
            // check if it is a data descriptor
            if (!(property instanceof UserAccessorProperty)) {
                if (property.isWritable()) {
                    return false;
                }
            }
            if (property.isConfigurable()) {
               return false;
            }
        }

        return true;
    }

    /**
     * Check prototype history for an existing property map with specified prototype.
     *
     * @param proto New prototype object.
     *
     * @return Existing {@link PropertyMap} or {@code null} if not found.
     */
    private PropertyMap checkProtoHistory(final ScriptObject proto) {
        final PropertyMap cachedMap;
        if (protoHistory != null) {
            final SoftReference<PropertyMap> weakMap = protoHistory.get(proto);
            cachedMap = (weakMap != null ? weakMap.get() : null);
        } else {
            cachedMap = null;
        }

        if (Context.DEBUG && cachedMap != null) {
            protoHistoryHit.increment();
        }

        return cachedMap;
    }

    /**
     * Add a map to the prototype history.
     *
     * @param newProto Prototype to add (key.)
     * @param newMap   {@link PropertyMap} associated with prototype.
     */
    private void addToProtoHistory(final ScriptObject newProto, final PropertyMap newMap) {
        if (protoHistory == null) {
            protoHistory = new WeakHashMap<>();
        }

        protoHistory.put(newProto, new SoftReference<>(newMap));
    }

    /**
     * Track the modification of the map.
     *
     * @param property Mapping property.
     * @param newMap   Modified {@link PropertyMap}.
     */
    private void addToHistory(final Property property, final PropertyMap newMap) {
        if (history == null) {
            history = new WeakHashMap<>();
        }

        history.put(property, softReferenceDerivationLimit == 0 ? new WeakReference<>(newMap) : new SoftReference<>(newMap));
    }

    /**
     * Check the history for a map that already has the given property added.
     *
     * @param property {@link Property} to add.
     *
     * @return Existing map or {@code null} if not found.
     */
    private PropertyMap checkHistory(final Property property) {

        if (history != null) {
            final Reference<PropertyMap> ref = history.get(property);
            final PropertyMap historicMap = ref == null ? null : ref.get();

            if (historicMap != null) {
                if (Context.DEBUG) {
                    historyHit.increment();
                }

                return historicMap;
            }
        }

        return null;
    }

    /**
     * Returns true if the two maps have identical properties in the same order, but allows the properties to differ in
     * their types. This method is mostly useful for tests.
     * @param otherMap the other map
     * @return true if this map has identical properties in the same order as the other map, allowing the properties to
     * differ in type.
     */
    public boolean equalsWithoutType(final PropertyMap otherMap) {
        if (properties.size() != otherMap.properties.size()) {
            return false;
        }

        final Iterator<Property> iter      = properties.values().iterator();
        final Iterator<Property> otherIter = otherMap.properties.values().iterator();

        while (iter.hasNext() && otherIter.hasNext()) {
            if (!iter.next().equalsWithoutType(otherIter.next())) {
                return false;
            }
        }

        return true;
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder();

        sb.append(Debug.id(this));
        sb.append(" = {\n");

        for (final Property property : getProperties()) {
            sb.append('\t');
            sb.append(property);
            sb.append('\n');
        }

        sb.append('}');

        return sb.toString();
    }

    @Override
    public Iterator<Object> iterator() {
        return new PropertyMapIterator(this);
    }

    /**
     * Check if this map contains properties with valid array keys
     *
     * @return {@code true} if this map contains properties with valid array keys
     */
    public final boolean containsArrayKeys() {
        return (flags & CONTAINS_ARRAY_KEYS) != 0;
    }

    /**
     * Test to see if {@link PropertyMap} is extensible.
     *
     * @return {@code true} if {@link PropertyMap} can be added to.
     */
    boolean isExtensible() {
        return (flags & NOT_EXTENSIBLE) == 0;
    }

    /**
     * Test to see if {@link PropertyMap} is not extensible or any properties
     * can not be modified.
     *
     * @return {@code true} if {@link PropertyMap} is sealed.
     */
    boolean isSealed() {
        return !isExtensible() && !anyConfigurable();
    }

    /**
     * Test to see if {@link PropertyMap} is not extensible or all properties
     * can not be modified.
     *
     * @return {@code true} if {@link PropertyMap} is frozen.
     */
    boolean isFrozen() {
        return !isExtensible() && allFrozen();
    }

    /**
     * Return a free field slot for this map, or {@code -1} if none is available.
     *
     * @return free field slot or -1
     */
    int getFreeFieldSlot() {
        if (freeSlots != null) {
            final int freeSlot = freeSlots.nextSetBit(0);
            if (freeSlot > -1 && freeSlot < fieldMaximum) {
                return freeSlot;
            }
        }
        if (fieldCount < fieldMaximum) {
            return fieldCount;
        }
        return -1;
    }

    /**
     * Get a free spill slot for this map.
     *
     * @return free spill slot
     */
    int getFreeSpillSlot() {
        if (freeSlots != null) {
            final int freeSlot = freeSlots.nextSetBit(fieldMaximum);
            if (freeSlot > -1) {
                return freeSlot - fieldMaximum;
            }
        }
        return spillLength;
    }

    /**
     * Return a property map with the same layout that is associated with the new prototype object.
     *
     * @param newProto New prototype object to replace oldProto.
     * @return New {@link PropertyMap} with prototype changed.
     */
    public synchronized PropertyMap changeProto(final ScriptObject newProto) {
        final PropertyMap nextMap = checkProtoHistory(newProto);
        if (nextMap != null) {
            return nextMap;
        }

        if (Context.DEBUG) {
            setProtoNewMapCount.increment();
        }

        final PropertyMap newMap = makeUnsharedCopy();
        addToProtoHistory(newProto, newMap);

        return newMap;
    }

    /**
     * Make a copy of this property map with the shared prototype field set to null. Note that this is
     * only necessary for shared maps of top-level objects. Shared prototype maps represented by
     * {@link SharedPropertyMap} are automatically converted to plain property maps when they evolve.
     *
     * @return a copy with the shared proto map unset
     */
    PropertyMap makeUnsharedCopy() {
        final PropertyMap newMap = new PropertyMap(this);
        newMap.sharedProtoMap = null;
        return newMap;
    }

    /**
     * Set a reference to the expected parent prototype map. This is used for class-like
     * structures where we only want to use a top-level property map if all of the
     * prototype property maps have not been modified.
     *
     * @param protoMap weak reference to the prototype property map
     */
    void setSharedProtoMap(final SharedPropertyMap protoMap) {
        sharedProtoMap = protoMap;
    }

    /**
     * Get the expected prototype property map if it is known, or null.
     *
     * @return parent map or null
     */
    public PropertyMap getSharedProtoMap() {
        return sharedProtoMap;
    }

    /**
     * Returns {@code true} if this map has been used as a shared prototype map (i.e. as a prototype
     * for a JavaScript constructor function) and has not had properties added, deleted or replaced since then.
     * @return true if this is a valid shared prototype map
     */
    boolean isValidSharedProtoMap() {
        return false;
    }

    /**
     * Returns the shared prototype switch point, or null if this is not a shared prototype map.
     * @return the shared prototype switch point, or null
     */
    SwitchPoint getSharedProtoSwitchPoint() {
        return null;
    }

    /**
     * Return true if this map has a shared prototype map which has either been invalidated or does
     * not match the map of {@code proto}.
     * @param prototype the prototype object
     * @return true if this is an invalid shared map for {@code prototype}
     */
    boolean isInvalidSharedMapFor(final ScriptObject prototype) {
        return sharedProtoMap != null
                && (!sharedProtoMap.isValidSharedProtoMap() || prototype == null || sharedProtoMap != prototype.getMap());
    }

    /**
     * {@link PropertyMap} iterator.
     */
    private static class PropertyMapIterator implements Iterator<Object> {
        /** Property iterator. */
        final Iterator<Property> iter;

        /** Current Property. */
        Property property;

        /**
         * Constructor.
         *
         * @param propertyMap {@link PropertyMap} to iterate over.
         */
        PropertyMapIterator(final PropertyMap propertyMap) {
            iter = Arrays.asList(propertyMap.properties.getProperties()).iterator();
            property = iter.hasNext() ? iter.next() : null;
            skipNotEnumerable();
        }

        /**
         * Ignore properties that are not enumerable.
         */
        private void skipNotEnumerable() {
            while (property != null && !property.isEnumerable()) {
                property = iter.hasNext() ? iter.next() : null;
            }
        }

        @Override
        public boolean hasNext() {
            return property != null;
        }

        @Override
        public Object next() {
            if (property == null) {
                throw new NoSuchElementException();
            }

            final Object key = property.getKey();
            property = iter.next();
            skipNotEnumerable();

            return key;
        }

        @Override
        public void remove() {
            throw new UnsupportedOperationException("remove");
        }
    }

    /*
     * Debugging and statistics.
     */

    /**
     * Debug helper function that returns the diff of two property maps, only
     * displaying the information that is different and in which map it exists
     * compared to the other map. Can be used to e.g. debug map guards and
     * investigate why they fail, causing relink
     *
     * @param map0 the first property map
     * @param map1 the second property map
     *
     * @return property map diff as string
     */
    public static String diff(final PropertyMap map0, final PropertyMap map1) {
        final StringBuilder sb = new StringBuilder();

        if (map0 != map1) {
           sb.append(">>> START: Map diff");
           boolean found = false;

           for (final Property p : map0.getProperties()) {
               final Property p2 = map1.findProperty(p.getKey());
               if (p2 == null) {
                   sb.append("FIRST ONLY : [").append(p).append("]");
                   found = true;
               } else if (p2 != p) {
                   sb.append("DIFFERENT  : [").append(p).append("] != [").append(p2).append("]");
                   found = true;
               }
           }

           for (final Property p2 : map1.getProperties()) {
               final Property p1 = map0.findProperty(p2.getKey());
               if (p1 == null) {
                   sb.append("SECOND ONLY: [").append(p2).append("]");
                   found = true;
               }
           }

           //assert found;

           if (!found) {
                sb.append(map0).
                    append("!=").
                    append(map1);
           }

           sb.append("<<< END: Map diff\n");
        }

        return sb.toString();
    }

    // counters updated only in debug mode
    private static LongAdder count;
    private static LongAdder clonedCount;
    private static LongAdder historyHit;
    private static LongAdder protoInvalidations;
    private static LongAdder protoHistoryHit;
    private static LongAdder setProtoNewMapCount;
    static {
        if (Context.DEBUG) {
            count = new LongAdder();
            clonedCount = new LongAdder();
            historyHit = new LongAdder();
            protoInvalidations = new LongAdder();
            protoHistoryHit = new LongAdder();
            setProtoNewMapCount = new LongAdder();
        }
    }

    /**
     * @return Total number of maps.
     */
    public static long getCount() {
        return count.longValue();
    }

    /**
     * @return The number of maps that were cloned.
     */
    public static long getClonedCount() {
        return clonedCount.longValue();
    }

    /**
     * @return The number of times history was successfully used.
     */
    public static long getHistoryHit() {
        return historyHit.longValue();
    }

    /**
     * @return The number of times prototype changes caused invalidation.
     */
    public static long getProtoInvalidations() {
        return protoInvalidations.longValue();
    }

    /**
     * @return The number of times proto history was successfully used.
     */
    public static long getProtoHistoryHit() {
        return protoHistoryHit.longValue();
    }

    /**
     * @return The number of times prototypes were modified.
     */
    public static long getSetProtoNewMapCount() {
        return setProtoNewMapCount.longValue();
    }
}
