< prev index next >

src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/PropertySwitchPoints.java

Print this page

        

@@ -23,238 +23,196 @@
  * questions.
  */
 
 package jdk.nashorn.internal.runtime;
 
+import java.lang.invoke.SwitchPoint;
+import java.util.Collections;
 import java.util.Map;
 import java.util.Set;
 import java.util.WeakHashMap;
 import java.util.concurrent.atomic.LongAdder;
 
 /**
- * Helper class to manage property listeners and notification.
+ * Helper class for tracking and invalidation of switchpoints for inherited properties.
  */
-public class PropertyListeners {
+public class PropertySwitchPoints {
 
-    private Map<Object, WeakPropertyMapSet> listeners;
+    private final Map<Object, WeakSwitchPointSet> switchPointMap = new WeakHashMap<>();
+
+    private final static SwitchPoint[] EMPTY_SWITCHPOINT_ARRAY = new SwitchPoint[0];
 
     // These counters are updated in debug mode
-    private static LongAdder listenersAdded;
-    private static LongAdder listenersRemoved;
+    private static LongAdder switchPointsAdded;
+    private static LongAdder switchPointsInvalidated;
 
     static {
         if (Context.DEBUG) {
-            listenersAdded = new LongAdder();
-            listenersRemoved = new LongAdder();
+            switchPointsAdded = new LongAdder();
+            switchPointsInvalidated = new LongAdder();
         }
     }
 
     /**
      * Copy constructor
-     * @param listener listener to copy
+     *
+     * @param switchPoints Proto switchpoints to copy
      */
-    PropertyListeners(final PropertyListeners listener) {
-        if (listener != null && listener.listeners != null) {
-            this.listeners = new WeakHashMap<>();
+    private PropertySwitchPoints(final PropertySwitchPoints switchPoints) {
+        if (switchPoints != null) {
             // We need to copy the nested weak sets in order to avoid concurrent modification issues, see JDK-8146274
-            synchronized (listener) {
-                for (final Map.Entry<Object, WeakPropertyMapSet> entry : listener.listeners.entrySet()) {
-                    this.listeners.put(entry.getKey(), new WeakPropertyMapSet(entry.getValue()));
+            synchronized (switchPoints) {
+                for (final Map.Entry<Object, WeakSwitchPointSet> entry : switchPoints.switchPointMap.entrySet()) {
+                    this.switchPointMap.put(entry.getKey(), new WeakSwitchPointSet(entry.getValue()));
                 }
             }
         }
     }
 
     /**
-     * Return aggregate listeners added to all PropertyListenerManagers
-     * @return the listenersAdded
+     * Return aggregate switchpoints added to all ProtoSwitchPoints
+     * @return the number of switchpoints added
      */
-    public static long getListenersAdded() {
-        return listenersAdded.longValue();
+    public static long getSwitchPointsAdded() {
+        return switchPointsAdded.longValue();
     }
 
     /**
-     * Return aggregate listeners removed from all PropertyListenerManagers
-     * @return the listenersRemoved
+     * Return aggregate switchPointMap invalidated in all ProtoSwitchPoints
+     * @return the number of switchpoints invalidated
      */
-    public static long getListenersRemoved() {
-        return listenersRemoved.longValue();
+    public static long getSwitchPointsInvalidated() {
+        return switchPointsInvalidated.longValue();
     }
 
     /**
-     * Return number of listeners added to a ScriptObject.
+     * Return number of property switchPoints added to a ScriptObject.
      * @param obj the object
-     * @return the listener count
+     * @return the switchpoint count
      */
-    public static int getListenerCount(final ScriptObject obj) {
-        return obj.getMap().getListenerCount();
+    public static int getSwitchPointCount(final ScriptObject obj) {
+        return obj.getMap().getSwitchPointCount();
     }
 
     /**
-     * Return the number of listeners added to this PropertyListeners instance.
-     * @return the listener count;
+     * Return the number of switchpoints added to this ProtoSwitchPoints instance.
+     * @return the switchpoint count;
      */
-    public int getListenerCount() {
-        return listeners == null ? 0 : listeners.size();
+    int getSwitchPointCount() {
+        return switchPointMap.size();
     }
 
-    // Property listener management methods
-
     /**
-     * Add {@code propertyMap} as property listener to {@code listeners} using key {@code key} by
-     * creating and returning a new {@code PropertyListeners} instance.
+     * Add {@code switchPoint} to the switchpoints for the property identified by {@code key}, creating
+     * and returning a new {@code ProtoSwitchPoints} instance if the switchpoint was not already contained
      *
-     * @param listeners the original property listeners instance, may be null
+     * @param oldSwitchPoints the original PropertySwitchPoints instance. May be null
      * @param key the property key
-     * @param propertyMap the property map
-     * @return the new property map
+     * @param switchPoint the switchpoint to be added
+     * @return the new PropertySwitchPoints instance, or this instance if switchpoint was already contained
      */
-    public static PropertyListeners addListener(final PropertyListeners listeners, final String key, final PropertyMap propertyMap) {
-        final PropertyListeners newListeners;
-        if (listeners == null || !listeners.containsListener(key, propertyMap)) {
-            newListeners = new PropertyListeners(listeners);
-            newListeners.addListener(key, propertyMap);
-            return newListeners;
+    static PropertySwitchPoints addSwitchPoint(final PropertySwitchPoints oldSwitchPoints, final String key, final SwitchPoint switchPoint) {
+        if (oldSwitchPoints == null || !oldSwitchPoints.contains(key, switchPoint)) {
+            final PropertySwitchPoints newSwitchPoints = new PropertySwitchPoints(oldSwitchPoints);
+            newSwitchPoints.add(key, switchPoint);
+            return newSwitchPoints;
         }
-        return listeners;
+        return oldSwitchPoints;
     }
 
     /**
-     * Checks whether {@code propertyMap} is registered as listener with {@code key}.
+     * Checks whether {@code switchPoint} is contained in {@code key}'s set.
      *
      * @param key the property key
-     * @param propertyMap the property map
-     * @return true if property map is registered with property key
+     * @param switchPoint the switchPoint
+     * @return true if switchpoint is already contained for key
      */
-    synchronized boolean containsListener(final String key, final PropertyMap propertyMap) {
-        if (listeners == null) {
-            return false;
-        }
-        final WeakPropertyMapSet set = listeners.get(key);
-        return set != null && set.contains(propertyMap);
+    private synchronized boolean contains(final String key, final SwitchPoint switchPoint) {
+        final WeakSwitchPointSet set = this.switchPointMap.get(key);
+        return set != null && set.contains(switchPoint);
     }
 
-    /**
-     * Add a property listener to this object.
-     *
-     * @param propertyMap The property listener that is added.
-     */
-    synchronized final void addListener(final String key, final PropertyMap propertyMap) {
+    private synchronized void add(final String key, final SwitchPoint switchPoint) {
         if (Context.DEBUG) {
-            listenersAdded.increment();
-        }
-        if (listeners == null) {
-            listeners = new WeakHashMap<>();
+            switchPointsAdded.increment();
         }
 
-        WeakPropertyMapSet set = listeners.get(key);
+        WeakSwitchPointSet set = this.switchPointMap.get(key);
         if (set == null) {
-            set = new WeakPropertyMapSet();
-            listeners.put(key, set);
-        }
-        if (!set.contains(propertyMap)) {
-            set.add(propertyMap);
-        }
+            set = new WeakSwitchPointSet();
+            this.switchPointMap.put(key, set);
     }
 
-    /**
-     * A new property is being added.
-     *
-     * @param prop The new Property added.
-     */
-    public synchronized void propertyAdded(final Property prop) {
-        if (listeners != null) {
-            final WeakPropertyMapSet set = listeners.get(prop.getKey());
-            if (set != null) {
-                for (final PropertyMap propertyMap : set.elements()) {
-                    propertyMap.propertyAdded(prop, false);
-                }
-                listeners.remove(prop.getKey());
-                if (Context.DEBUG) {
-                    listenersRemoved.increment();
-                }
-            }
-        }
+        set.add(switchPoint);
     }
 
-    /**
-     * An existing property is being deleted.
-     *
-     * @param prop The property being deleted.
-     */
-    public synchronized void propertyDeleted(final Property prop) {
-        if (listeners != null) {
-            final WeakPropertyMapSet set = listeners.get(prop.getKey());
-            if (set != null) {
-                for (final PropertyMap propertyMap : set.elements()) {
-                    propertyMap.propertyDeleted(prop, false);
-                }
-                listeners.remove(prop.getKey());
-                if (Context.DEBUG) {
-                    listenersRemoved.increment();
-                }
-            }
+    Set<SwitchPoint> getSwitchPoints(final Object key) {
+        WeakSwitchPointSet switchPointSet = switchPointMap.get(key);
+        if (switchPointSet != null) {
+            return switchPointSet.elements();
         }
+
+        return Collections.emptySet();
     }
 
     /**
-     * An existing Property is being replaced with a new Property.
-     *
-     * @param oldProp The old property that is being replaced.
-     * @param newProp The new property that replaces the old property.
+     * Invalidate all switchpoints for the given property.
      *
+     * @param prop The property to invalidate.
      */
-    public synchronized void propertyModified(final Property oldProp, final Property newProp) {
-        if (listeners != null) {
-            final WeakPropertyMapSet set = listeners.get(oldProp.getKey());
+    synchronized void invalidateProperty(final Property prop) {
+        final WeakSwitchPointSet set = switchPointMap.get(prop.getKey());
             if (set != null) {
-                for (final PropertyMap propertyMap : set.elements()) {
-                    propertyMap.propertyModified(oldProp, newProp, false);
-                }
-                listeners.remove(oldProp.getKey());
                 if (Context.DEBUG) {
-                    listenersRemoved.increment();
-                }
+                switchPointsInvalidated.add(set.size());
             }
+            final SwitchPoint[] switchPoints = set.elements().toArray(EMPTY_SWITCHPOINT_ARRAY);
+            SwitchPoint.invalidateAll(switchPoints);
+            this.switchPointMap.remove(prop.getKey());
         }
     }
 
+
     /**
-     * Callback for when a proto is changed
+     * Invalidate all our switchpoints.
      */
-    public synchronized void protoChanged() {
-        if (listeners != null) {
-            for (final WeakPropertyMapSet set : listeners.values()) {
-                for (final PropertyMap propertyMap : set.elements()) {
-                    propertyMap.protoChanged(false);
-                }
+    synchronized void invalidateAll() {
+        for (final WeakSwitchPointSet set : switchPointMap.values()) {
+            if (Context.DEBUG) {
+                switchPointsInvalidated.add(set.size());
             }
-            listeners.clear();
+            final SwitchPoint[] switchPoints = set.elements().toArray(EMPTY_SWITCHPOINT_ARRAY);
+            SwitchPoint.invalidateAll(switchPoints);
         }
+        switchPointMap.clear();
     }
 
-    private static class WeakPropertyMapSet {
+    private static class WeakSwitchPointSet {
 
-        private final WeakHashMap<PropertyMap, Boolean> map;
+        private final WeakHashMap<SwitchPoint, Void> map;
 
-        WeakPropertyMapSet() {
-            this.map = new WeakHashMap<>();
+        WeakSwitchPointSet() {
+            map = new WeakHashMap<>();
         }
 
-        WeakPropertyMapSet(final WeakPropertyMapSet set) {
-            this.map = new WeakHashMap<>(set.map);
+        WeakSwitchPointSet(final WeakSwitchPointSet set) {
+            map = new WeakHashMap<>(set.map);
         }
 
-        void add(final PropertyMap propertyMap) {
-            map.put(propertyMap, Boolean.TRUE);
+        void add(final SwitchPoint switchPoint) {
+            map.put(switchPoint, null);
         }
 
-        boolean contains(final PropertyMap propertyMap) {
-            return map.containsKey(propertyMap);
+        boolean contains(final SwitchPoint switchPoint) {
+            return map.containsKey(switchPoint);
         }
 
-        Set<PropertyMap> elements() {
+        Set<SwitchPoint> elements() {
             return map.keySet();
         }
 
+        int size() {
+            return map.size();
+        }
+
     }
 }
< prev index next >