changeset 1435:2e6dd4d24206

RT-23079: CacheEntry in StyleHelper should weakly reference the shared cache from StylesheetContainer styleCache
author David Grieve<david.grieve@oracle.com>
date Thu, 12 Jul 2012 00:28:13 -0400
parents 1953b610d096
children a844e4fd4abf
files javafx-ui-common/src/com/sun/javafx/css/StyleHelper.java javafx-ui-common/src/com/sun/javafx/css/StyleManager.java
diffstat 2 files changed, 33 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/javafx-ui-common/src/com/sun/javafx/css/StyleHelper.java	Wed Jul 11 16:46:20 2012 +0100
+++ b/javafx-ui-common/src/com/sun/javafx/css/StyleHelper.java	Thu Jul 12 00:28:13 2012 -0400
@@ -303,7 +303,8 @@
         // member will be null. If this is a local cache, then this member
         // will point to the shared cache for the same states.
         //
-        private final CacheEntry sharedCache;
+        // RT-23079 - weakly reference the shared CacheEntry
+        private final Reference<CacheEntry> sharedCacheRef;
 
         private CacheEntry(long[] states) {
             this(states, null);
@@ -312,16 +313,20 @@
         private CacheEntry(long[] states, CacheEntry sharedCache) {
             this.states = states;
             this.values = new HashMap<String,CalculatedValue>();
-            this.sharedCache = sharedCache;
+            this.sharedCacheRef = new WeakReference<CacheEntry>(sharedCache);
         }
 
         private CalculatedValue get(String property) {
+            
             CalculatedValue cv = null;
             if (values.isEmpty() == false) {
                 cv = values.get(property);
             }
-            if (cv == null && sharedCache != null) {
-                cv = sharedCache.values.get(property);
+            if (cv == null && sharedCacheRef != null) {
+                final CacheEntry ce = sharedCacheRef.get();
+                if (ce != null) cv = ce.values.get(property);
+                // if referent is null, we should skip the value. 
+                else cv = SKIP; 
             }
             return cv;
         }
@@ -334,7 +339,7 @@
             // then use local cache if the font origin is inline or user and
             // the value was calculated from a relative size unit. 
             final boolean isLocal = 
-                (sharedCache == null
+                (sharedCacheRef == null
                     || cv.origin == Origin.INLINE
                     || cv.origin == Origin.USER)
                 || (cv.isRelative &&
@@ -343,9 +348,13 @@
             
             if (isLocal) {
                 values.put(property, cv);
-            } else if (sharedCache.values.containsKey(property) == false) {
-                // don't override value already in shared cache.
-                sharedCache.values.put(property, cv);
+            } else {
+                // if isLocal is false, then sharedCacheRef cannot be null. 
+                final CacheEntry ce = sharedCacheRef.get();
+                if (ce != null && ce.values.containsKey(property) == false) {
+                    // don't override value already in shared cache.
+                    ce.values.put(property, cv);
+                }
             }
         }
 
@@ -435,7 +444,7 @@
         final int max = entries.size();
         for (int n=0; n<max; n++) {
             CacheEntry entry = entries.get(n);
-            assert (entry.sharedCache != null);
+            assert (entry.sharedCacheRef != null);
             entry.values.clear();
             entry.font = null;
         }
@@ -738,15 +747,23 @@
         //
                 
         final CacheEntry cacheEntry = getCacheEntry(node, pseudoClassStates);
-        if (cacheEntry == null) {
+        if (cacheEntry == null 
+            || (cacheEntry.sharedCacheRef != null 
+                && cacheEntry.sharedCacheRef.get() == null)) {
             // If cacheEntry is null, then the StyleManager Cache from which
             // this StyleHelper was created has been blown away and this
             // StyleHelper is no good. If this is the case, we need to tell
             // this node to reapply CSS
+            //
+            // RT-23079 - if this is local cache, then the sharedCacheRef 
+            // will not be null. If sharedCacheRef is not null, but its 
+            // referent is null, then the styleMap in the StylesheetContainer
+            // has been cleared and we're working with a cache that is no good.
+            // 
             node.impl_reapplyCSS();
             return;
         }
-
+        
         //
         // if this node has a style map, then we'll populate it.
         // 
--- a/javafx-ui-common/src/com/sun/javafx/css/StyleManager.java	Wed Jul 11 16:46:20 2012 +0100
+++ b/javafx-ui-common/src/com/sun/javafx/css/StyleManager.java	Thu Jul 12 00:28:13 2012 -0400
@@ -1360,7 +1360,7 @@
                 for(int n=0; n<nElements; n++) newKey.styleClass.add(styleClass.get(n));
                 newKey.indices = hasParentStylesheets ? indicesOfParentsWithStylesheets : null;
                 
-                cache = new Cache(this, rules, pseudoclassStateMask, impactsChildren);
+                cache = new Cache(rules, pseudoclassStateMask, impactsChildren);
                 cacheMap.put(newKey, cache);
                 
                 // RT-22565: remember where this cache is used if there are 
@@ -1376,7 +1376,7 @@
             // Return the style helper looked up by the cache. The cache will
             // create a style helper if necessary (and possible), so we don't
             // have to worry about that part.
-            StyleMap smap = cache.getStyleMap(node);
+            StyleMap smap = cache.getStyleMap(this, node);
             if (smap == null) return null;
             
             StyleHelper helper = 
@@ -1435,7 +1435,7 @@
      * Creates and caches maps of styles, reusing them as often as practical.
      */
     private static class Cache {
-        private final StylesheetContainer owner;
+
         // this must be initialized to the appropriate possible rules when
         // the helper cache is created by the StylesheetContainer
         private final List<Rule> rules;
@@ -1443,15 +1443,14 @@
         private final boolean impactsChildren;
         private final Map<Long, StyleMap> cache;
         
-        Cache(StylesheetContainer owner, List<Rule> rules, long pseudoclassStateMask, boolean impactsChildren) {
-            this.owner = owner;
+        Cache(List<Rule> rules, long pseudoclassStateMask, boolean impactsChildren) {
             this.rules = rules;
             this.pseudoclassStateMask = pseudoclassStateMask;
             this.impactsChildren = impactsChildren;
             this.cache = new HashMap<Long, StyleMap>();
         }
 
-        private StyleMap getStyleMap(Node node) {
+        private StyleMap getStyleMap(StylesheetContainer owner, Node node) {
 
             // If this set of rules (which may be empty) impacts children,
             // then this node will get a StyleHelper.