< 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 >