nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/PropertyMap.java
author hannesw
Thu, 05 Feb 2015 14:42:14 +0100
changeset 28786 679fd2d26470
parent 27356 2d407b9be8b0
child 29534 f0a6624dce16
permissions -rw-r--r--
8062141: Various performance issues parsing JSON Reviewed-by: lagergren, attila
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
     1
/*
16151
97c1e756ae1e 8005663: Update copyright year to 2013
jlaskey
parents: 16147
diff changeset
     2
 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
     4
 *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    10
 *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    15
 * accompanied this code).
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    16
 *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    20
 *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    23
 * questions.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    24
 */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    25
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    26
package jdk.nashorn.internal.runtime;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    27
17513
b9a691fc1df5 8006220: Simplify PropertyMaps
jlaskey
parents: 16774
diff changeset
    28
import static jdk.nashorn.internal.runtime.PropertyHashMap.EMPTY_HASHMAP;
21441
0b98be59e3cb 8026858: Array length does not handle defined properties correctly
hannesw
parents: 19619
diff changeset
    29
import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.getArrayIndex;
0b98be59e3cb 8026858: Array length does not handle defined properties correctly
hannesw
parents: 19619
diff changeset
    30
import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    31
23767
7c0614b75e23 8038638: Persistent store for compiled scripts
hannesw
parents: 23084
diff changeset
    32
import java.io.IOException;
7c0614b75e23 8038638: Persistent store for compiled scripts
hannesw
parents: 23084
diff changeset
    33
import java.io.ObjectInputStream;
7c0614b75e23 8038638: Persistent store for compiled scripts
hannesw
parents: 23084
diff changeset
    34
import java.io.ObjectOutputStream;
7c0614b75e23 8038638: Persistent store for compiled scripts
hannesw
parents: 23084
diff changeset
    35
import java.io.Serializable;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    36
import java.lang.invoke.SwitchPoint;
23084
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
    37
import java.lang.ref.SoftReference;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    38
import java.util.Arrays;
26060
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
    39
import java.util.BitSet;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    40
import java.util.Collection;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    41
import java.util.HashMap;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    42
import java.util.Iterator;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    43
import java.util.NoSuchElementException;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    44
import java.util.WeakHashMap;
23767
7c0614b75e23 8038638: Persistent store for compiled scripts
hannesw
parents: 23084
diff changeset
    45
import jdk.nashorn.internal.scripts.JO;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    46
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    47
/**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    48
 * Map of object properties. The PropertyMap is the "template" for JavaScript object
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    49
 * layouts. It contains a map with prototype names as keys and {@link Property} instances
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    50
 * as values. A PropertyMap is typically passed to the {@link ScriptObject} constructor
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    51
 * to form the seed map for the ScriptObject.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    52
 * <p>
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    53
 * All property maps are immutable. If a property is added, modified or removed, the mutator
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    54
 * will return a new map.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    55
 */
23767
7c0614b75e23 8038638: Persistent store for compiled scripts
hannesw
parents: 23084
diff changeset
    56
public final class PropertyMap implements Iterable<Object>, Serializable {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    57
    /** Used for non extensible PropertyMaps, negative logic as the normal case is extensible. See {@link ScriptObject#preventExtensions()} */
17513
b9a691fc1df5 8006220: Simplify PropertyMaps
jlaskey
parents: 16774
diff changeset
    58
    public static final int NOT_EXTENSIBLE        = 0b0000_0001;
21441
0b98be59e3cb 8026858: Array length does not handle defined properties correctly
hannesw
parents: 19619
diff changeset
    59
    /** Does this map contain valid array keys? */
0b98be59e3cb 8026858: Array length does not handle defined properties correctly
hannesw
parents: 19619
diff changeset
    60
    public static final int CONTAINS_ARRAY_KEYS   = 0b0000_0010;
17513
b9a691fc1df5 8006220: Simplify PropertyMaps
jlaskey
parents: 16774
diff changeset
    61
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    62
    /** Map status flags. */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    63
    private int flags;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    64
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    65
    /** Map of properties. */
23767
7c0614b75e23 8038638: Persistent store for compiled scripts
hannesw
parents: 23084
diff changeset
    66
    private transient PropertyHashMap properties;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    67
17513
b9a691fc1df5 8006220: Simplify PropertyMaps
jlaskey
parents: 16774
diff changeset
    68
    /** Number of fields in use. */
b9a691fc1df5 8006220: Simplify PropertyMaps
jlaskey
parents: 16774
diff changeset
    69
    private int fieldCount;
b9a691fc1df5 8006220: Simplify PropertyMaps
jlaskey
parents: 16774
diff changeset
    70
b9a691fc1df5 8006220: Simplify PropertyMaps
jlaskey
parents: 16774
diff changeset
    71
    /** Number of fields available. */
24721
81f70e23cd3b 8036127: Prototype filter needs to be applied to getter guard as well, not just getter
lagergren
parents: 24719
diff changeset
    72
    private final int fieldMaximum;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    73
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    74
    /** Length of spill in use. */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    75
    private int spillLength;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    76
23767
7c0614b75e23 8038638: Persistent store for compiled scripts
hannesw
parents: 23084
diff changeset
    77
    /** Structure class name */
7c0614b75e23 8038638: Persistent store for compiled scripts
hannesw
parents: 23084
diff changeset
    78
    private String className;
7c0614b75e23 8038638: Persistent store for compiled scripts
hannesw
parents: 23084
diff changeset
    79
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    80
    /** {@link SwitchPoint}s for gets on inherited properties. */
23767
7c0614b75e23 8038638: Persistent store for compiled scripts
hannesw
parents: 23084
diff changeset
    81
    private transient HashMap<String, SwitchPoint> protoGetSwitches;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    82
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    83
    /** History of maps, used to limit map duplication. */
23767
7c0614b75e23 8038638: Persistent store for compiled scripts
hannesw
parents: 23084
diff changeset
    84
    private transient WeakHashMap<Property, SoftReference<PropertyMap>> history;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    85
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    86
    /** History of prototypes, used to limit map duplication. */
27356
2d407b9be8b0 8062132: Nashorn incorrectly binds this for constructor created by another function
hannesw
parents: 27307
diff changeset
    87
    private transient WeakHashMap<ScriptObject, SoftReference<PropertyMap>> protoHistory;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    88
23084
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
    89
    /** property listeners */
23767
7c0614b75e23 8038638: Persistent store for compiled scripts
hannesw
parents: 23084
diff changeset
    90
    private transient PropertyListeners listeners;
7c0614b75e23 8038638: Persistent store for compiled scripts
hannesw
parents: 23084
diff changeset
    91
26060
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
    92
    private transient BitSet freeSlots;
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
    93
23767
7c0614b75e23 8038638: Persistent store for compiled scripts
hannesw
parents: 23084
diff changeset
    94
    private static final long serialVersionUID = -7041836752008732533L;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    95
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    96
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    97
     * Constructor.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    98
     *
18852
604c1d681b6f 8017084: Use spill properties for large object literals
hannesw
parents: 18618
diff changeset
    99
     * @param properties   A {@link PropertyHashMap} with initial contents.
604c1d681b6f 8017084: Use spill properties for large object literals
hannesw
parents: 18618
diff changeset
   100
     * @param fieldCount   Number of fields in use.
17513
b9a691fc1df5 8006220: Simplify PropertyMaps
jlaskey
parents: 16774
diff changeset
   101
     * @param fieldMaximum Number of fields available.
18852
604c1d681b6f 8017084: Use spill properties for large object literals
hannesw
parents: 18618
diff changeset
   102
     * @param spillLength  Number of spill slots used.
21441
0b98be59e3cb 8026858: Array length does not handle defined properties correctly
hannesw
parents: 19619
diff changeset
   103
     * @param containsArrayKeys True if properties contain numeric keys
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   104
     */
23767
7c0614b75e23 8038638: Persistent store for compiled scripts
hannesw
parents: 23084
diff changeset
   105
    private PropertyMap(final PropertyHashMap properties, final String className, final int fieldCount,
7c0614b75e23 8038638: Persistent store for compiled scripts
hannesw
parents: 23084
diff changeset
   106
                        final int fieldMaximum, final int spillLength, final boolean containsArrayKeys) {
17513
b9a691fc1df5 8006220: Simplify PropertyMaps
jlaskey
parents: 16774
diff changeset
   107
        this.properties   = properties;
23767
7c0614b75e23 8038638: Persistent store for compiled scripts
hannesw
parents: 23084
diff changeset
   108
        this.className    = className;
17513
b9a691fc1df5 8006220: Simplify PropertyMaps
jlaskey
parents: 16774
diff changeset
   109
        this.fieldCount   = fieldCount;
b9a691fc1df5 8006220: Simplify PropertyMaps
jlaskey
parents: 16774
diff changeset
   110
        this.fieldMaximum = fieldMaximum;
18852
604c1d681b6f 8017084: Use spill properties for large object literals
hannesw
parents: 18618
diff changeset
   111
        this.spillLength  = spillLength;
21441
0b98be59e3cb 8026858: Array length does not handle defined properties correctly
hannesw
parents: 19619
diff changeset
   112
        if (containsArrayKeys) {
0b98be59e3cb 8026858: Array length does not handle defined properties correctly
hannesw
parents: 19619
diff changeset
   113
            setContainsArrayKeys();
0b98be59e3cb 8026858: Array length does not handle defined properties correctly
hannesw
parents: 19619
diff changeset
   114
        }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   115
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   116
        if (Context.DEBUG) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   117
            count++;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   118
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   119
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   120
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   121
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   122
     * Cloning constructor.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   123
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   124
     * @param propertyMap Existing property map.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   125
     * @param properties  A {@link PropertyHashMap} with a new set of properties.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   126
     */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   127
    private PropertyMap(final PropertyMap propertyMap, final PropertyHashMap properties) {
17513
b9a691fc1df5 8006220: Simplify PropertyMaps
jlaskey
parents: 16774
diff changeset
   128
        this.properties   = properties;
23084
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   129
        this.flags        = propertyMap.flags;
17513
b9a691fc1df5 8006220: Simplify PropertyMaps
jlaskey
parents: 16774
diff changeset
   130
        this.spillLength  = propertyMap.spillLength;
b9a691fc1df5 8006220: Simplify PropertyMaps
jlaskey
parents: 16774
diff changeset
   131
        this.fieldCount   = propertyMap.fieldCount;
b9a691fc1df5 8006220: Simplify PropertyMaps
jlaskey
parents: 16774
diff changeset
   132
        this.fieldMaximum = propertyMap.fieldMaximum;
23084
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   133
        // We inherit the parent property listeners instance. It will be cloned when a new listener is added.
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   134
        this.listeners    = propertyMap.listeners;
26060
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   135
        this.freeSlots    = propertyMap.freeSlots;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   136
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   137
        if (Context.DEBUG) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   138
            count++;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   139
            clonedCount++;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   140
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   141
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   142
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   143
    /**
17513
b9a691fc1df5 8006220: Simplify PropertyMaps
jlaskey
parents: 16774
diff changeset
   144
     * Cloning constructor.
b9a691fc1df5 8006220: Simplify PropertyMaps
jlaskey
parents: 16774
diff changeset
   145
     *
b9a691fc1df5 8006220: Simplify PropertyMaps
jlaskey
parents: 16774
diff changeset
   146
     * @param propertyMap Existing property map.
b9a691fc1df5 8006220: Simplify PropertyMaps
jlaskey
parents: 16774
diff changeset
   147
      */
b9a691fc1df5 8006220: Simplify PropertyMaps
jlaskey
parents: 16774
diff changeset
   148
    private PropertyMap(final PropertyMap propertyMap) {
b9a691fc1df5 8006220: Simplify PropertyMaps
jlaskey
parents: 16774
diff changeset
   149
        this(propertyMap, propertyMap.properties);
b9a691fc1df5 8006220: Simplify PropertyMaps
jlaskey
parents: 16774
diff changeset
   150
    }
b9a691fc1df5 8006220: Simplify PropertyMaps
jlaskey
parents: 16774
diff changeset
   151
23767
7c0614b75e23 8038638: Persistent store for compiled scripts
hannesw
parents: 23084
diff changeset
   152
    private void writeObject(final ObjectOutputStream out) throws IOException {
7c0614b75e23 8038638: Persistent store for compiled scripts
hannesw
parents: 23084
diff changeset
   153
        out.defaultWriteObject();
7c0614b75e23 8038638: Persistent store for compiled scripts
hannesw
parents: 23084
diff changeset
   154
        out.writeObject(properties.getProperties());
7c0614b75e23 8038638: Persistent store for compiled scripts
hannesw
parents: 23084
diff changeset
   155
    }
7c0614b75e23 8038638: Persistent store for compiled scripts
hannesw
parents: 23084
diff changeset
   156
7c0614b75e23 8038638: Persistent store for compiled scripts
hannesw
parents: 23084
diff changeset
   157
    private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
7c0614b75e23 8038638: Persistent store for compiled scripts
hannesw
parents: 23084
diff changeset
   158
        in.defaultReadObject();
7c0614b75e23 8038638: Persistent store for compiled scripts
hannesw
parents: 23084
diff changeset
   159
7c0614b75e23 8038638: Persistent store for compiled scripts
hannesw
parents: 23084
diff changeset
   160
        final Property[] props = (Property[]) in.readObject();
7c0614b75e23 8038638: Persistent store for compiled scripts
hannesw
parents: 23084
diff changeset
   161
        this.properties = EMPTY_HASHMAP.immutableAdd(props);
7c0614b75e23 8038638: Persistent store for compiled scripts
hannesw
parents: 23084
diff changeset
   162
7c0614b75e23 8038638: Persistent store for compiled scripts
hannesw
parents: 23084
diff changeset
   163
        assert className != null;
7c0614b75e23 8038638: Persistent store for compiled scripts
hannesw
parents: 23084
diff changeset
   164
        final Class<?> structure = Context.forStructureClass(className);
24778
2ff5d7041566 8044638: Tidy up Nashorn codebase for code standards
attila
parents: 24769
diff changeset
   165
        for (final Property prop : props) {
23767
7c0614b75e23 8038638: Persistent store for compiled scripts
hannesw
parents: 23084
diff changeset
   166
            prop.initMethodHandles(structure);
7c0614b75e23 8038638: Persistent store for compiled scripts
hannesw
parents: 23084
diff changeset
   167
        }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   168
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   169
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   170
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   171
     * Public property map allocator.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   172
     *
21441
0b98be59e3cb 8026858: Array length does not handle defined properties correctly
hannesw
parents: 19619
diff changeset
   173
     * <p>It is the caller's responsibility to make sure that {@code properties} does not contain
0b98be59e3cb 8026858: Array length does not handle defined properties correctly
hannesw
parents: 19619
diff changeset
   174
     * properties with keys that are valid array indices.</p>
0b98be59e3cb 8026858: Array length does not handle defined properties correctly
hannesw
parents: 19619
diff changeset
   175
     *
18852
604c1d681b6f 8017084: Use spill properties for large object literals
hannesw
parents: 18618
diff changeset
   176
     * @param properties   Collection of initial properties.
24993
b707d46bae40 8046898: Make sure that lazy compilation is the default, remove redundant "enable lazy compilation" flags, added warning message if compile logging is enabled and lazy is switched off. Verified existing test suite code coverage equivalence between lazy and eager.
lagergren
parents: 24778
diff changeset
   177
     * @param className    class name
18852
604c1d681b6f 8017084: Use spill properties for large object literals
hannesw
parents: 18618
diff changeset
   178
     * @param fieldCount   Number of fields in use.
17513
b9a691fc1df5 8006220: Simplify PropertyMaps
jlaskey
parents: 16774
diff changeset
   179
     * @param fieldMaximum Number of fields available.
18852
604c1d681b6f 8017084: Use spill properties for large object literals
hannesw
parents: 18618
diff changeset
   180
     * @param spillLength  Number of used spill slots.
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   181
     * @return New {@link PropertyMap}.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   182
     */
23767
7c0614b75e23 8038638: Persistent store for compiled scripts
hannesw
parents: 23084
diff changeset
   183
    public static PropertyMap newMap(final Collection<Property> properties, final String className, final int fieldCount, final int fieldMaximum,  final int spillLength) {
24721
81f70e23cd3b 8036127: Prototype filter needs to be applied to getter guard as well, not just getter
lagergren
parents: 24719
diff changeset
   184
        final PropertyHashMap newProperties = EMPTY_HASHMAP.immutableAdd(properties);
23767
7c0614b75e23 8038638: Persistent store for compiled scripts
hannesw
parents: 23084
diff changeset
   185
        return new PropertyMap(newProperties, className, fieldCount, fieldMaximum, spillLength, false);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   186
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   187
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   188
    /**
18855
408663ef8f66 8020015: shared PropertyMaps should not be used without duplication
sundar
parents: 18852
diff changeset
   189
     * Public property map allocator. Used by nasgen generated code.
21441
0b98be59e3cb 8026858: Array length does not handle defined properties correctly
hannesw
parents: 19619
diff changeset
   190
     *
0b98be59e3cb 8026858: Array length does not handle defined properties correctly
hannesw
parents: 19619
diff changeset
   191
     * <p>It is the caller's responsibility to make sure that {@code properties} does not contain
0b98be59e3cb 8026858: Array length does not handle defined properties correctly
hannesw
parents: 19619
diff changeset
   192
     * properties with keys that are valid array indices.</p>
0b98be59e3cb 8026858: Array length does not handle defined properties correctly
hannesw
parents: 19619
diff changeset
   193
     *
18855
408663ef8f66 8020015: shared PropertyMaps should not be used without duplication
sundar
parents: 18852
diff changeset
   194
     * @param properties Collection of initial properties.
408663ef8f66 8020015: shared PropertyMaps should not be used without duplication
sundar
parents: 18852
diff changeset
   195
     * @return New {@link PropertyMap}.
408663ef8f66 8020015: shared PropertyMaps should not be used without duplication
sundar
parents: 18852
diff changeset
   196
     */
408663ef8f66 8020015: shared PropertyMaps should not be used without duplication
sundar
parents: 18852
diff changeset
   197
    public static PropertyMap newMap(final Collection<Property> properties) {
24769
attila
parents: 24763 23767
diff changeset
   198
        return properties == null || properties.isEmpty()? newMap() : newMap(properties, JO.class.getName(), 0, 0, 0);
18855
408663ef8f66 8020015: shared PropertyMaps should not be used without duplication
sundar
parents: 18852
diff changeset
   199
    }
408663ef8f66 8020015: shared PropertyMaps should not be used without duplication
sundar
parents: 18852
diff changeset
   200
408663ef8f66 8020015: shared PropertyMaps should not be used without duplication
sundar
parents: 18852
diff changeset
   201
    /**
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   202
     * Return a sharable empty map.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   203
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   204
     * @return New empty {@link PropertyMap}.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   205
     */
18852
604c1d681b6f 8017084: Use spill properties for large object literals
hannesw
parents: 18618
diff changeset
   206
    public static PropertyMap newMap() {
23767
7c0614b75e23 8038638: Persistent store for compiled scripts
hannesw
parents: 23084
diff changeset
   207
        return new PropertyMap(EMPTY_HASHMAP, JO.class.getName(), 0, 0, 0, false);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   208
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   209
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   210
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   211
     * Return number of properties in the map.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   212
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   213
     * @return Number of properties.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   214
     */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   215
    public int size() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   216
        return properties.size();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   217
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   218
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   219
    /**
23084
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   220
     * Get the listeners of this map, or null if none exists
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   221
     *
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   222
     * @return the listeners
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   223
     */
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   224
    public PropertyListeners getListeners() {
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   225
        return listeners;
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   226
    }
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   227
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   228
    /**
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   229
     * Add {@code listenerMap} as a listener to this property map for the given {@code key}.
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   230
     *
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   231
     * @param key the property name
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   232
     * @param listenerMap the listener map
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   233
     */
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   234
    public void addListener(final String key, final PropertyMap listenerMap) {
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   235
        if (listenerMap != this) {
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   236
            // We need to clone listener instance when adding a new listener since we share
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   237
            // the listeners instance with our parent maps that don't need to see the new listener.
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   238
            listeners = PropertyListeners.addListener(listeners, key, listenerMap);
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   239
        }
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   240
    }
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   241
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   242
    /**
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   243
     * A new property is being added.
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   244
     *
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   245
     * @param property The new Property added.
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   246
     */
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   247
    public void propertyAdded(final Property property) {
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   248
        invalidateProtoGetSwitchPoint(property);
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   249
        if (listeners != null) {
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   250
            listeners.propertyAdded(property);
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   251
        }
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   252
    }
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   253
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   254
    /**
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   255
     * An existing property is being deleted.
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   256
     *
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   257
     * @param property The property being deleted.
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   258
     */
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   259
    public void propertyDeleted(final Property property) {
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   260
        invalidateProtoGetSwitchPoint(property);
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   261
        if (listeners != null) {
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   262
            listeners.propertyDeleted(property);
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   263
        }
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   264
    }
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   265
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   266
    /**
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   267
     * An existing property is being redefined.
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   268
     *
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   269
     * @param oldProperty The old property
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   270
     * @param newProperty The new property
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   271
     */
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   272
    public void propertyModified(final Property oldProperty, final Property newProperty) {
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   273
        invalidateProtoGetSwitchPoint(oldProperty);
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   274
        if (listeners != null) {
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   275
            listeners.propertyModified(oldProperty, newProperty);
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   276
        }
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   277
    }
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   278
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   279
    /**
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   280
     * The prototype of an object associated with this {@link PropertyMap} is changed.
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   281
     */
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   282
    public void protoChanged() {
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   283
        invalidateAllProtoGetSwitchPoints();
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   284
        if (listeners != null) {
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   285
            listeners.protoChanged();
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   286
        }
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   287
    }
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   288
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   289
    /**
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   290
     * Return a SwitchPoint used to track changes of a property in a prototype.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   291
     *
23084
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   292
     * @param key Property key.
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   293
     * @return A shared {@link SwitchPoint} for the property.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   294
     */
23084
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   295
    public synchronized SwitchPoint getSwitchPoint(final String key) {
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   296
        if (protoGetSwitches == null) {
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   297
            protoGetSwitches = new HashMap<>();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   298
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   299
23084
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   300
        SwitchPoint switchPoint = protoGetSwitches.get(key);
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   301
        if (switchPoint == null) {
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   302
            switchPoint = new SwitchPoint();
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   303
            protoGetSwitches.put(key, switchPoint);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   304
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   305
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   306
        return switchPoint;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   307
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   308
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   309
    /**
19619
4085b74056ee 8023368: Instance __proto__ property should exist and be writable.
sundar
parents: 19097
diff changeset
   310
     * Indicate that a prototype property has changed.
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   311
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   312
     * @param property {@link Property} to invalidate.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   313
     */
23084
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   314
    synchronized void invalidateProtoGetSwitchPoint(final Property property) {
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   315
        if (protoGetSwitches != null) {
18855
408663ef8f66 8020015: shared PropertyMaps should not be used without duplication
sundar
parents: 18852
diff changeset
   316
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   317
            final String key = property.getKey();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   318
            final SwitchPoint sp = protoGetSwitches.get(key);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   319
            if (sp != null) {
23084
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   320
                protoGetSwitches.remove(key);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   321
                if (Context.DEBUG) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   322
                    protoInvalidations++;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   323
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   324
                SwitchPoint.invalidateAll(new SwitchPoint[] { sp });
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   325
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   326
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   327
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   328
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   329
    /**
23084
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   330
     * Indicate that proto itself has changed in hierarchy somewhere.
19619
4085b74056ee 8023368: Instance __proto__ property should exist and be writable.
sundar
parents: 19097
diff changeset
   331
     */
23084
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   332
    synchronized void invalidateAllProtoGetSwitchPoints() {
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   333
        if (protoGetSwitches != null && !protoGetSwitches.isEmpty()) {
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   334
            if (Context.DEBUG) {
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   335
                protoInvalidations += protoGetSwitches.size();
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   336
            }
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   337
            SwitchPoint.invalidateAll(protoGetSwitches.values().toArray(new SwitchPoint[protoGetSwitches.values().size()]));
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   338
            protoGetSwitches.clear();
19619
4085b74056ee 8023368: Instance __proto__ property should exist and be writable.
sundar
parents: 19097
diff changeset
   339
        }
4085b74056ee 8023368: Instance __proto__ property should exist and be writable.
sundar
parents: 19097
diff changeset
   340
    }
4085b74056ee 8023368: Instance __proto__ property should exist and be writable.
sundar
parents: 19097
diff changeset
   341
4085b74056ee 8023368: Instance __proto__ property should exist and be writable.
sundar
parents: 19097
diff changeset
   342
    /**
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   343
     * Add a property to the map, re-binding its getters and setters,
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   344
     * if available, to a given receiver. This is typically the global scope. See
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   345
     * {@link ScriptObject#addBoundProperties(ScriptObject)}
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   346
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   347
     * @param property {@link Property} being added.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   348
     * @param bindTo   Object to bind to.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   349
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   350
     * @return New {@link PropertyMap} with {@link Property} added.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   351
     */
18860
e387fde9322a 8014785: Ability to extend global instance by binding properties of another object
sundar
parents: 18855
diff changeset
   352
    PropertyMap addPropertyBind(final AccessorProperty property, final Object bindTo) {
23084
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   353
        // No need to store bound property in the history as bound properties can't be reused.
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   354
        return addPropertyNoHistory(new AccessorProperty(property, bindTo));
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   355
    }
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   356
26060
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   357
    // Get a logical slot index for a property, with spill slot 0 starting at fieldMaximum.
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   358
    private int logicalSlotIndex(final Property property) {
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   359
        final int slot = property.getSlot();
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   360
        if (slot < 0) {
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   361
            return -1;
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   362
        }
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   363
        return property.isSpill() ? slot + fieldMaximum : slot;
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   364
    }
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   365
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   366
    // Update boundaries and flags after a property has been added
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   367
    private void updateFlagsAndBoundaries(final Property newProperty) {
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   368
        if(newProperty.isSpill()) {
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   369
            spillLength = Math.max(spillLength, newProperty.getSlot() + 1);
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   370
        } else {
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   371
            fieldCount = Math.max(fieldCount, newProperty.getSlot() + 1);
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   372
        }
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   373
        if (isValidArrayIndex(getArrayIndex(newProperty.getKey()))) {
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   374
            setContainsArrayKeys();
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   375
        }
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   376
    }
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   377
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   378
    // Update the free slots bitmap for a property that has been deleted and/or added.
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   379
    private void updateFreeSlots(final Property oldProperty, final Property newProperty) {
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   380
        // Free slots bitset is possibly shared with parent map, so we must clone it before making modifications.
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   381
        boolean freeSlotsCloned = false;
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   382
        if (oldProperty != null) {
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   383
            final int slotIndex = logicalSlotIndex(oldProperty);
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   384
            if (slotIndex >= 0) {
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   385
                final BitSet newFreeSlots = freeSlots == null ? new BitSet() : (BitSet)freeSlots.clone();
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   386
                assert !newFreeSlots.get(slotIndex);
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   387
                newFreeSlots.set(slotIndex);
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   388
                freeSlots = newFreeSlots;
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   389
                freeSlotsCloned = true;
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   390
            }
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   391
        }
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   392
        if (freeSlots != null && newProperty != null) {
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   393
            final int slotIndex = logicalSlotIndex(newProperty);
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   394
            if (slotIndex > -1 && freeSlots.get(slotIndex)) {
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   395
                final BitSet newFreeSlots = freeSlotsCloned ? freeSlots : ((BitSet)freeSlots.clone());
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   396
                newFreeSlots.clear(slotIndex);
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   397
                freeSlots = newFreeSlots.isEmpty() ? null : newFreeSlots;
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   398
            }
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   399
        }
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   400
    }
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   401
23084
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   402
    /**
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   403
     * Add a property to the map without adding it to the history. This should be used for properties that
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   404
     * can't be shared such as bound properties, or properties that are expected to be added only once.
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   405
     *
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   406
     * @param property {@link Property} being added.
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   407
     * @return New {@link PropertyMap} with {@link Property} added.
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   408
     */
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   409
    public PropertyMap addPropertyNoHistory(final Property property) {
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   410
        if (listeners != null) {
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   411
            listeners.propertyAdded(property);
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   412
        }
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   413
        final PropertyHashMap newProperties = properties.immutableAdd(property);
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   414
        final PropertyMap newMap = new PropertyMap(this, newProperties);
26060
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   415
        newMap.updateFlagsAndBoundaries(property);
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   416
        newMap.updateFreeSlots(null, property);
23084
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   417
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   418
        return newMap;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   419
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   420
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   421
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   422
     * Add a property to the map.  Cloning or using an existing map if available.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   423
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   424
     * @param property {@link Property} being added.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   425
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   426
     * @return New {@link PropertyMap} with {@link Property} added.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   427
     */
18617
f6fe338f62c3 8008458: Strict functions dont share property map
jlaskey
parents: 18325
diff changeset
   428
    public PropertyMap addProperty(final Property property) {
23084
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   429
        if (listeners != null) {
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   430
            listeners.propertyAdded(property);
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   431
        }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   432
        PropertyMap newMap = checkHistory(property);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   433
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   434
        if (newMap == null) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   435
            final PropertyHashMap newProperties = properties.immutableAdd(property);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   436
            newMap = new PropertyMap(this, newProperties);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   437
            addToHistory(property, newMap);
26060
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   438
            newMap.updateFlagsAndBoundaries(property);
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   439
            newMap.updateFreeSlots(null, property);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   440
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   441
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   442
        return newMap;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   443
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   444
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   445
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   446
     * Remove a property from a map. Cloning or using an existing map if available.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   447
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   448
     * @param property {@link Property} being removed.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   449
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   450
     * @return New {@link PropertyMap} with {@link Property} removed or {@code null} if not found.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   451
     */
16228
df28320aa080 8007900: Function binding is inefficient
attila
parents: 16224
diff changeset
   452
    public PropertyMap deleteProperty(final Property property) {
23084
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   453
        if (listeners != null) {
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   454
            listeners.propertyDeleted(property);
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   455
        }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   456
        PropertyMap newMap = checkHistory(property);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   457
        final String key = property.getKey();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   458
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   459
        if (newMap == null && properties.containsKey(key)) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   460
            final PropertyHashMap newProperties = properties.immutableRemove(key);
26060
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   461
            final boolean isSpill = property.isSpill();
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   462
            final int slot = property.getSlot();
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   463
            // If deleted property was last field or spill slot we can make it reusable by reducing field/slot count.
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   464
            // Otherwise mark it as free in free slots bitset.
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   465
            if (isSpill && slot >= 0 && slot == spillLength - 1) {
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   466
                newMap = new PropertyMap(newProperties, className, fieldCount, fieldMaximum, spillLength - 1, containsArrayKeys());
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   467
                newMap.freeSlots = freeSlots;
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   468
            } else if (!isSpill && slot >= 0 && slot == fieldCount - 1) {
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   469
                newMap = new PropertyMap(newProperties, className, fieldCount - 1, fieldMaximum, spillLength, containsArrayKeys());
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   470
                newMap.freeSlots = freeSlots;
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   471
            } else {
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   472
                newMap = new PropertyMap(this, newProperties);
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   473
                newMap.updateFreeSlots(property, null);
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   474
            }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   475
            addToHistory(property, newMap);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   476
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   477
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   478
        return newMap;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   479
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   480
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   481
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   482
     * Replace an existing property with a new one.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   483
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   484
     * @param oldProperty Property to replace.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   485
     * @param newProperty New {@link Property}.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   486
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   487
     * @return New {@link PropertyMap} with {@link Property} replaced.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   488
     */
28786
679fd2d26470 8062141: Various performance issues parsing JSON
hannesw
parents: 27356
diff changeset
   489
    public PropertyMap replaceProperty(final Property oldProperty, final Property newProperty) {
23084
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   490
        if (listeners != null) {
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   491
            listeners.propertyModified(oldProperty, newProperty);
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   492
        }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   493
        // Add replaces existing property.
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   494
        final PropertyHashMap newProperties = properties.immutableReplace(oldProperty, newProperty);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   495
        final PropertyMap newMap = new PropertyMap(this, newProperties);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   496
        /*
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   497
         * See ScriptObject.modifyProperty and ScriptObject.setUserAccessors methods.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   498
         *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   499
         * This replaceProperty method is called only for the following three cases:
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   500
         *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   501
         *   1. To change flags OR TYPE of an old (cloned) property. We use the same spill slots.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   502
         *   2. To change one UserAccessor property with another - user getter or setter changed via
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   503
         *      Object.defineProperty function. Again, same spill slots are re-used.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   504
         *   3. Via ScriptObject.setUserAccessors method to set user getter and setter functions
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   505
         *      replacing the dummy AccessorProperty with null method handles (added during map init).
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   506
         *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   507
         * In case (1) and case(2), the property type of old and new property is same. For case (3),
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   508
         * the old property is an AccessorProperty and the new one is a UserAccessorProperty property.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   509
         */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   510
24721
81f70e23cd3b 8036127: Prototype filter needs to be applied to getter guard as well, not just getter
lagergren
parents: 24719
diff changeset
   511
        final boolean sameType = oldProperty.getClass() == newProperty.getClass();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   512
        assert sameType ||
24721
81f70e23cd3b 8036127: Prototype filter needs to be applied to getter guard as well, not just getter
lagergren
parents: 24719
diff changeset
   513
                oldProperty instanceof AccessorProperty &&
81f70e23cd3b 8036127: Prototype filter needs to be applied to getter guard as well, not just getter
lagergren
parents: 24719
diff changeset
   514
                newProperty instanceof UserAccessorProperty :
27307
62ed492cbe63 8062401: User accessors require boxing and do not support optimistic types
hannesw
parents: 26768
diff changeset
   515
            "arbitrary replaceProperty attempted " + sameType + " oldProperty=" + oldProperty.getClass() + " newProperty=" + newProperty.getClass() + " [" + oldProperty.getLocalType() + " => " + newProperty.getLocalType() + "]";
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   516
23084
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   517
        newMap.flags = flags;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   518
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   519
        /*
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   520
         * spillLength remains same in case (1) and (2) because of slot reuse. Only for case (3), we need
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   521
         * to add spill count of the newly added UserAccessorProperty property.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   522
         */
26060
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   523
        if (!sameType) {
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   524
            newMap.spillLength = Math.max(spillLength, newProperty.getSlot() + 1);
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   525
            newMap.updateFreeSlots(oldProperty, newProperty);
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   526
        }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   527
        return newMap;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   528
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   529
19097
f544a2ea40ef 8021262: Make nashorn access checks consistent with underlying dynalink
sundar
parents: 18860
diff changeset
   530
    /**
18617
f6fe338f62c3 8008458: Strict functions dont share property map
jlaskey
parents: 18325
diff changeset
   531
     * Make a new UserAccessorProperty property. getter and setter functions are stored in
f6fe338f62c3 8008458: Strict functions dont share property map
jlaskey
parents: 18325
diff changeset
   532
     * this ScriptObject and slot values are used in property object. Note that slots
f6fe338f62c3 8008458: Strict functions dont share property map
jlaskey
parents: 18325
diff changeset
   533
     * are assigned speculatively and should be added to map before adding other
f6fe338f62c3 8008458: Strict functions dont share property map
jlaskey
parents: 18325
diff changeset
   534
     * properties.
19097
f544a2ea40ef 8021262: Make nashorn access checks consistent with underlying dynalink
sundar
parents: 18860
diff changeset
   535
     *
f544a2ea40ef 8021262: Make nashorn access checks consistent with underlying dynalink
sundar
parents: 18860
diff changeset
   536
     * @param key the property name
f544a2ea40ef 8021262: Make nashorn access checks consistent with underlying dynalink
sundar
parents: 18860
diff changeset
   537
     * @param propertyFlags attribute flags of the property
f544a2ea40ef 8021262: Make nashorn access checks consistent with underlying dynalink
sundar
parents: 18860
diff changeset
   538
     * @return the newly created UserAccessorProperty
18617
f6fe338f62c3 8008458: Strict functions dont share property map
jlaskey
parents: 18325
diff changeset
   539
     */
f6fe338f62c3 8008458: Strict functions dont share property map
jlaskey
parents: 18325
diff changeset
   540
    public UserAccessorProperty newUserAccessors(final String key, final int propertyFlags) {
26060
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   541
        return new UserAccessorProperty(key, propertyFlags, getFreeSpillSlot());
18617
f6fe338f62c3 8008458: Strict functions dont share property map
jlaskey
parents: 18325
diff changeset
   542
    }
f6fe338f62c3 8008458: Strict functions dont share property map
jlaskey
parents: 18325
diff changeset
   543
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   544
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   545
     * Find a property in the map.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   546
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   547
     * @param key Key to search for.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   548
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   549
     * @return {@link Property} matching key.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   550
     */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   551
    public Property findProperty(final String key) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   552
        return properties.find(key);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   553
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   554
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   555
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   556
     * Adds all map properties from another map.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   557
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   558
     * @param other The source of properties.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   559
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   560
     * @return New {@link PropertyMap} with added properties.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   561
     */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   562
    public PropertyMap addAll(final PropertyMap other) {
16216
46ed48fd84d3 8007273: Creation of ScriptFunctions can be refactored
hannesw
parents: 16201
diff changeset
   563
        assert this != other : "adding property map to itself";
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   564
        final Property[] otherProperties = other.properties.getProperties();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   565
        final PropertyHashMap newProperties = properties.immutableAdd(otherProperties);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   566
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   567
        final PropertyMap newMap = new PropertyMap(this, newProperties);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   568
        for (final Property property : otherProperties) {
26060
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   569
            // This method is only safe to use with non-slotted, native getter/setter properties
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   570
            assert property.getSlot() == -1;
26648
9a64e15eff37 8056978: ClassCastException: cannot cast jdk.nashorn.internal.scripts.JO*
hannesw
parents: 26068
diff changeset
   571
            assert !(isValidArrayIndex(getArrayIndex(property.getKey())));
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   572
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   573
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   574
        return newMap;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   575
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   576
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   577
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   578
     * Return an array of all properties.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   579
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   580
     * @return Properties as an array.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   581
     */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   582
    public Property[] getProperties() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   583
        return properties.getProperties();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   584
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   585
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   586
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   587
     * Prevents the map from having additional properties.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   588
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   589
     * @return New map with {@link #NOT_EXTENSIBLE} flag set.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   590
     */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   591
    PropertyMap preventExtensions() {
17513
b9a691fc1df5 8006220: Simplify PropertyMaps
jlaskey
parents: 16774
diff changeset
   592
        final PropertyMap newMap = new PropertyMap(this);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   593
        newMap.flags |= NOT_EXTENSIBLE;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   594
        return newMap;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   595
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   596
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   597
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   598
     * Prevents properties in map from being modified.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   599
     *
16154
de44634fa4ec 8005782: get rid of javadoc errors, warnings in nashorn build
sundar
parents: 16152
diff changeset
   600
     * @return New map with {@link #NOT_EXTENSIBLE} flag set and properties with
de44634fa4ec 8005782: get rid of javadoc errors, warnings in nashorn build
sundar
parents: 16152
diff changeset
   601
     * {@link Property#NOT_CONFIGURABLE} set.
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   602
     */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   603
    PropertyMap seal() {
17513
b9a691fc1df5 8006220: Simplify PropertyMaps
jlaskey
parents: 16774
diff changeset
   604
        PropertyHashMap newProperties = EMPTY_HASHMAP;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   605
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   606
        for (final Property oldProperty :  properties.getProperties()) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   607
            newProperties = newProperties.immutableAdd(oldProperty.addFlags(Property.NOT_CONFIGURABLE));
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   608
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   609
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   610
        final PropertyMap newMap = new PropertyMap(this, newProperties);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   611
        newMap.flags |= NOT_EXTENSIBLE;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   612
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   613
        return newMap;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   614
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   615
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   616
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   617
     * Prevents properties in map from being modified or written to.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   618
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   619
     * @return New map with {@link #NOT_EXTENSIBLE} flag set and properties with
16154
de44634fa4ec 8005782: get rid of javadoc errors, warnings in nashorn build
sundar
parents: 16152
diff changeset
   620
     * {@link Property#NOT_CONFIGURABLE} and {@link Property#NOT_WRITABLE} set.
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   621
     */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   622
    PropertyMap freeze() {
17513
b9a691fc1df5 8006220: Simplify PropertyMaps
jlaskey
parents: 16774
diff changeset
   623
        PropertyHashMap newProperties = EMPTY_HASHMAP;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   624
24721
81f70e23cd3b 8036127: Prototype filter needs to be applied to getter guard as well, not just getter
lagergren
parents: 24719
diff changeset
   625
        for (final Property oldProperty : properties.getProperties()) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   626
            int propertyFlags = Property.NOT_CONFIGURABLE;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   627
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   628
            if (!(oldProperty instanceof UserAccessorProperty)) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   629
                propertyFlags |= Property.NOT_WRITABLE;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   630
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   631
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   632
            newProperties = newProperties.immutableAdd(oldProperty.addFlags(propertyFlags));
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   633
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   634
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   635
        final PropertyMap newMap = new PropertyMap(this, newProperties);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   636
        newMap.flags |= NOT_EXTENSIBLE;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   637
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   638
        return newMap;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   639
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   640
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   641
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   642
     * Check for any configurable properties.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   643
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   644
     * @return {@code true} if any configurable.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   645
     */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   646
    private boolean anyConfigurable() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   647
        for (final Property property : properties.getProperties()) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   648
            if (property.isConfigurable()) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   649
               return true;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   650
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   651
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   652
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   653
        return false;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   654
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   655
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   656
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   657
     * Check if all properties are frozen.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   658
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   659
     * @return {@code true} if all are frozen.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   660
     */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   661
    private boolean allFrozen() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   662
        for (final Property property : properties.getProperties()) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   663
            // check if it is a data descriptor
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   664
            if (!(property instanceof UserAccessorProperty)) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   665
                if (property.isWritable()) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   666
                    return false;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   667
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   668
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   669
            if (property.isConfigurable()) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   670
               return false;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   671
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   672
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   673
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   674
        return true;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   675
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   676
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   677
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   678
     * Check prototype history for an existing property map with specified prototype.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   679
     *
27356
2d407b9be8b0 8062132: Nashorn incorrectly binds this for constructor created by another function
hannesw
parents: 27307
diff changeset
   680
     * @param proto New prototype object.
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   681
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   682
     * @return Existing {@link PropertyMap} or {@code null} if not found.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   683
     */
27356
2d407b9be8b0 8062132: Nashorn incorrectly binds this for constructor created by another function
hannesw
parents: 27307
diff changeset
   684
    private PropertyMap checkProtoHistory(final ScriptObject proto) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   685
        final PropertyMap cachedMap;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   686
        if (protoHistory != null) {
27356
2d407b9be8b0 8062132: Nashorn incorrectly binds this for constructor created by another function
hannesw
parents: 27307
diff changeset
   687
            final SoftReference<PropertyMap> weakMap = protoHistory.get(proto);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   688
            cachedMap = (weakMap != null ? weakMap.get() : null);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   689
        } else {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   690
            cachedMap = null;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   691
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   692
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   693
        if (Context.DEBUG && cachedMap != null) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   694
            protoHistoryHit++;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   695
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   696
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   697
        return cachedMap;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   698
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   699
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   700
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   701
     * Add a map to the prototype history.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   702
     *
27356
2d407b9be8b0 8062132: Nashorn incorrectly binds this for constructor created by another function
hannesw
parents: 27307
diff changeset
   703
     * @param newProto Prototype to add (key.)
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   704
     * @param newMap   {@link PropertyMap} associated with prototype.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   705
     */
27356
2d407b9be8b0 8062132: Nashorn incorrectly binds this for constructor created by another function
hannesw
parents: 27307
diff changeset
   706
    private void addToProtoHistory(final ScriptObject newProto, final PropertyMap newMap) {
16759
ecf99910fc31 8011219: Regression with recent PropertyMap history changes
hannesw
parents: 16758
diff changeset
   707
        if (protoHistory == null) {
ecf99910fc31 8011219: Regression with recent PropertyMap history changes
hannesw
parents: 16758
diff changeset
   708
            protoHistory = new WeakHashMap<>();
ecf99910fc31 8011219: Regression with recent PropertyMap history changes
hannesw
parents: 16758
diff changeset
   709
        }
16758
4f7379c41907 8011095: PropertyHashMap.rehash() does not grow enough
jlaskey
parents: 16275
diff changeset
   710
27356
2d407b9be8b0 8062132: Nashorn incorrectly binds this for constructor created by another function
hannesw
parents: 27307
diff changeset
   711
        protoHistory.put(newProto, new SoftReference<>(newMap));
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   712
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   713
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   714
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   715
     * Track the modification of the map.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   716
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   717
     * @param property Mapping property.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   718
     * @param newMap   Modified {@link PropertyMap}.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   719
     */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   720
    private void addToHistory(final Property property, final PropertyMap newMap) {
24763
20971b9687ec 8043605: Enable history for empty property maps
attila
parents: 24727
diff changeset
   721
        if (history == null) {
20971b9687ec 8043605: Enable history for empty property maps
attila
parents: 24727
diff changeset
   722
            history = new WeakHashMap<>();
20971b9687ec 8043605: Enable history for empty property maps
attila
parents: 24727
diff changeset
   723
        }
16774
745fe7d2536d 8011540: PropertyMap histories should not begin with empty map
jlaskey
parents: 16759
diff changeset
   724
24763
20971b9687ec 8043605: Enable history for empty property maps
attila
parents: 24727
diff changeset
   725
        history.put(property, new SoftReference<>(newMap));
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   726
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   727
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   728
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   729
     * Check the history for a map that already has the given property added.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   730
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   731
     * @param property {@link Property} to add.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   732
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   733
     * @return Existing map or {@code null} if not found.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   734
     */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   735
    private PropertyMap checkHistory(final Property property) {
23084
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   736
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   737
        if (history != null) {
24727
attila
parents: 24726 23084
diff changeset
   738
            final SoftReference<PropertyMap> ref = history.get(property);
23084
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   739
            final PropertyMap historicMap = ref == null ? null : ref.get();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   740
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   741
            if (historicMap != null) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   742
                if (Context.DEBUG) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   743
                    historyHit++;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   744
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   745
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   746
                return historicMap;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   747
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   748
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   749
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   750
        return null;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   751
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   752
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   753
    /**
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   754
     * Returns true if the two maps have identical properties in the same order, but allows the properties to differ in
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   755
     * their types. This method is mostly useful for tests.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   756
     * @param otherMap the other map
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   757
     * @return true if this map has identical properties in the same order as the other map, allowing the properties to
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   758
     * differ in type.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   759
     */
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   760
    public boolean equalsWithoutType(final PropertyMap otherMap) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   761
        if (properties.size() != otherMap.properties.size()) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   762
            return false;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   763
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   764
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   765
        final Iterator<Property> iter      = properties.values().iterator();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   766
        final Iterator<Property> otherIter = otherMap.properties.values().iterator();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   767
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   768
        while (iter.hasNext() && otherIter.hasNext()) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   769
            if (!iter.next().equalsWithoutType(otherIter.next())) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   770
                return false;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   771
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   772
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   773
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   774
        return true;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   775
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   776
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   777
    @Override
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   778
    public String toString() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   779
        final StringBuilder sb = new StringBuilder();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   780
24725
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
   781
        sb.append(Debug.id(this));
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
   782
        sb.append(" = {\n");
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   783
24726
34410e0545b1 8037967: Broke the build, by commiting without saving the last review comment
lagergren
parents: 24725
diff changeset
   784
        for (final Property property : getProperties()) {
24725
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
   785
            sb.append('\t');
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   786
            sb.append(property);
24725
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
   787
            sb.append('\n');
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   788
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   789
24725
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
   790
        sb.append('}');
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   791
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   792
        return sb.toString();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   793
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   794
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   795
    @Override
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   796
    public Iterator<Object> iterator() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   797
        return new PropertyMapIterator(this);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   798
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   799
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   800
    /**
21441
0b98be59e3cb 8026858: Array length does not handle defined properties correctly
hannesw
parents: 19619
diff changeset
   801
     * Check if this map contains properties with valid array keys
0b98be59e3cb 8026858: Array length does not handle defined properties correctly
hannesw
parents: 19619
diff changeset
   802
     *
0b98be59e3cb 8026858: Array length does not handle defined properties correctly
hannesw
parents: 19619
diff changeset
   803
     * @return {@code true} if this map contains properties with valid array keys
0b98be59e3cb 8026858: Array length does not handle defined properties correctly
hannesw
parents: 19619
diff changeset
   804
     */
0b98be59e3cb 8026858: Array length does not handle defined properties correctly
hannesw
parents: 19619
diff changeset
   805
    public final boolean containsArrayKeys() {
0b98be59e3cb 8026858: Array length does not handle defined properties correctly
hannesw
parents: 19619
diff changeset
   806
        return (flags & CONTAINS_ARRAY_KEYS) != 0;
0b98be59e3cb 8026858: Array length does not handle defined properties correctly
hannesw
parents: 19619
diff changeset
   807
    }
0b98be59e3cb 8026858: Array length does not handle defined properties correctly
hannesw
parents: 19619
diff changeset
   808
0b98be59e3cb 8026858: Array length does not handle defined properties correctly
hannesw
parents: 19619
diff changeset
   809
    /**
0b98be59e3cb 8026858: Array length does not handle defined properties correctly
hannesw
parents: 19619
diff changeset
   810
     * Flag this object as having array keys in defined properties
0b98be59e3cb 8026858: Array length does not handle defined properties correctly
hannesw
parents: 19619
diff changeset
   811
     */
0b98be59e3cb 8026858: Array length does not handle defined properties correctly
hannesw
parents: 19619
diff changeset
   812
    private void setContainsArrayKeys() {
0b98be59e3cb 8026858: Array length does not handle defined properties correctly
hannesw
parents: 19619
diff changeset
   813
        flags |= CONTAINS_ARRAY_KEYS;
0b98be59e3cb 8026858: Array length does not handle defined properties correctly
hannesw
parents: 19619
diff changeset
   814
    }
0b98be59e3cb 8026858: Array length does not handle defined properties correctly
hannesw
parents: 19619
diff changeset
   815
0b98be59e3cb 8026858: Array length does not handle defined properties correctly
hannesw
parents: 19619
diff changeset
   816
    /**
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   817
     * Test to see if {@link PropertyMap} is extensible.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   818
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   819
     * @return {@code true} if {@link PropertyMap} can be added to.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   820
     */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   821
    boolean isExtensible() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   822
        return (flags & NOT_EXTENSIBLE) == 0;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   823
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   824
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   825
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   826
     * Test to see if {@link PropertyMap} is not extensible or any properties
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   827
     * can not be modified.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   828
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   829
     * @return {@code true} if {@link PropertyMap} is sealed.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   830
     */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   831
    boolean isSealed() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   832
        return !isExtensible() && !anyConfigurable();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   833
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   834
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   835
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   836
     * Test to see if {@link PropertyMap} is not extensible or all properties
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   837
     * can not be modified.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   838
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   839
     * @return {@code true} if {@link PropertyMap} is frozen.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   840
     */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   841
    boolean isFrozen() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   842
        return !isExtensible() && allFrozen();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   843
    }
26060
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   844
17513
b9a691fc1df5 8006220: Simplify PropertyMaps
jlaskey
parents: 16774
diff changeset
   845
    /**
26060
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   846
     * Return a free field slot for this map, or {@code -1} if none is available.
17513
b9a691fc1df5 8006220: Simplify PropertyMaps
jlaskey
parents: 16774
diff changeset
   847
     *
26060
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   848
     * @return free field slot or -1
17513
b9a691fc1df5 8006220: Simplify PropertyMaps
jlaskey
parents: 16774
diff changeset
   849
     */
26060
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   850
    int getFreeFieldSlot() {
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   851
        if (freeSlots != null) {
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   852
            final int freeSlot = freeSlots.nextSetBit(0);
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   853
            if (freeSlot > -1 && freeSlot < fieldMaximum) {
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   854
                return freeSlot;
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   855
            }
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   856
        }
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   857
        if (fieldCount < fieldMaximum) {
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   858
            return fieldCount;
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   859
        }
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   860
        return -1;
17513
b9a691fc1df5 8006220: Simplify PropertyMaps
jlaskey
parents: 16774
diff changeset
   861
    }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   862
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   863
    /**
26060
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   864
     * Get a free spill slot for this map.
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   865
     *
26060
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   866
     * @return free spill slot
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   867
     */
26060
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   868
    int getFreeSpillSlot() {
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   869
        if (freeSlots != null) {
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   870
            final int freeSlot = freeSlots.nextSetBit(fieldMaximum);
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   871
            if (freeSlot > -1) {
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   872
                return freeSlot - fieldMaximum;
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   873
            }
50a029a28ecb 8044851: nashorn properties leak memory
hannesw
parents: 25421
diff changeset
   874
        }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   875
        return spillLength;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   876
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   877
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   878
    /**
23084
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   879
     * Return a property map with the same layout that is associated with the new prototype object.
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   880
     *
17513
b9a691fc1df5 8006220: Simplify PropertyMaps
jlaskey
parents: 16774
diff changeset
   881
     * @param newProto New prototype object to replace oldProto.
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   882
     * @return New {@link PropertyMap} with prototype changed.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   883
     */
23084
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   884
    public PropertyMap changeProto(final ScriptObject newProto) {
18855
408663ef8f66 8020015: shared PropertyMaps should not be used without duplication
sundar
parents: 18852
diff changeset
   885
27356
2d407b9be8b0 8062132: Nashorn incorrectly binds this for constructor created by another function
hannesw
parents: 27307
diff changeset
   886
        final PropertyMap nextMap = checkProtoHistory(newProto);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   887
        if (nextMap != null) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   888
            return nextMap;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   889
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   890
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   891
        if (Context.DEBUG) {
23084
6c5c02d1023a 8035948: Redesign property listeners for shared classes
hannesw
parents: 21441
diff changeset
   892
            setProtoNewMapCount++;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   893
        }
17513
b9a691fc1df5 8006220: Simplify PropertyMaps
jlaskey
parents: 16774
diff changeset
   894
b9a691fc1df5 8006220: Simplify PropertyMaps
jlaskey
parents: 16774
diff changeset
   895
        final PropertyMap newMap = new PropertyMap(this);
27356
2d407b9be8b0 8062132: Nashorn incorrectly binds this for constructor created by another function
hannesw
parents: 27307
diff changeset
   896
        addToProtoHistory(newProto, newMap);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   897
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   898
        return newMap;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   899
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   900
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   901
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   902
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   903
     * {@link PropertyMap} iterator.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   904
     */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   905
    private static class PropertyMapIterator implements Iterator<Object> {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   906
        /** Property iterator. */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   907
        final Iterator<Property> iter;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   908
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   909
        /** Current Property. */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   910
        Property property;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   911
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   912
        /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   913
         * Constructor.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   914
         *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   915
         * @param propertyMap {@link PropertyMap} to iterate over.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   916
         */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   917
        PropertyMapIterator(final PropertyMap propertyMap) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   918
            iter = Arrays.asList(propertyMap.properties.getProperties()).iterator();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   919
            property = iter.hasNext() ? iter.next() : null;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   920
            skipNotEnumerable();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   921
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   922
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   923
        /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   924
         * Ignore properties that are not enumerable.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   925
         */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   926
        private void skipNotEnumerable() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   927
            while (property != null && !property.isEnumerable()) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   928
                property = iter.hasNext() ? iter.next() : null;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   929
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   930
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   931
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   932
        @Override
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   933
        public boolean hasNext() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   934
            return property != null;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   935
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   936
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   937
        @Override
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   938
        public Object next() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   939
            if (property == null) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   940
                throw new NoSuchElementException();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   941
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   942
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   943
            final Object key = property.getKey();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   944
            property = iter.next();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   945
            skipNotEnumerable();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   946
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   947
            return key;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   948
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   949
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   950
        @Override
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   951
        public void remove() {
26768
751b0f427090 8025435: Optimistic builtins support, implemented initial optimistic versions of push, pop, and charCodeAt
lagergren
parents: 26648
diff changeset
   952
            throw new UnsupportedOperationException("remove");
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   953
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   954
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   955
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   956
    /*
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   957
     * Debugging and statistics.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   958
     */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   959
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   960
    /**
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   961
     * Debug helper function that returns the diff of two property maps, only
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   962
     * displaying the information that is different and in which map it exists
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   963
     * compared to the other map. Can be used to e.g. debug map guards and
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   964
     * investigate why they fail, causing relink
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   965
     *
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   966
     * @param map0 the first property map
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   967
     * @param map1 the second property map
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   968
     *
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   969
     * @return property map diff as string
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   970
     */
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   971
    public static String diff(final PropertyMap map0, final PropertyMap map1) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   972
        final StringBuilder sb = new StringBuilder();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   973
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   974
        if (map0 != map1) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   975
           sb.append(">>> START: Map diff");
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   976
           boolean found = false;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   977
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   978
           for (final Property p : map0.getProperties()) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   979
               final Property p2 = map1.findProperty(p.getKey());
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   980
               if (p2 == null) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   981
                   sb.append("FIRST ONLY : [" + p + "]");
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   982
                   found = true;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   983
               } else if (p2 != p) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   984
                   sb.append("DIFFERENT  : [" + p + "] != [" + p2 + "]");
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   985
                   found = true;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   986
               }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   987
           }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   988
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   989
           for (final Property p2 : map1.getProperties()) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   990
               final Property p1 = map0.findProperty(p2.getKey());
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   991
               if (p1 == null) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   992
                   sb.append("SECOND ONLY: [" + p2 + "]");
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   993
                   found = true;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   994
               }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   995
           }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   996
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   997
           //assert found;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   998
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
   999
           if (!found) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
  1000
                sb.append(map0).
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
  1001
                    append("!=").
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
  1002
                    append(map1);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
  1003
           }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
  1004
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
  1005
           sb.append("<<< END: Map diff\n");
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
  1006
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
  1007
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
  1008
        return sb.toString();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
  1009
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 21441
diff changeset
  1010
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1011
    // counters updated only in debug mode
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1012
    private static int count;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1013
    private static int clonedCount;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1014
    private static int historyHit;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1015
    private static int protoInvalidations;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1016
    private static int protoHistoryHit;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1017
    private static int setProtoNewMapCount;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1018
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1019
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1020
     * @return Total number of maps.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1021
     */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1022
    public static int getCount() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1023
        return count;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1024
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1025
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1026
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1027
     * @return The number of maps that were cloned.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1028
     */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1029
    public static int getClonedCount() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1030
        return clonedCount;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1031
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1032
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1033
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1034
     * @return The number of times history was successfully used.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1035
     */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1036
    public static int getHistoryHit() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1037
        return historyHit;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1038
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1039
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1040
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1041
     * @return The number of times prototype changes caused invalidation.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1042
     */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1043
    public static int getProtoInvalidations() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1044
        return protoInvalidations;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1045
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1046
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1047
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1048
     * @return The number of times proto history was successfully used.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1049
     */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1050
    public static int getProtoHistoryHit() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1051
        return protoHistoryHit;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1052
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1053
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1054
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1055
     * @return The number of times prototypes were modified.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1056
     */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1057
    public static int getSetProtoNewMapCount() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1058
        return setProtoNewMapCount;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1059
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1060
}