This is an automated email from the ASF dual-hosted git repository.

sunlan pushed a commit to branch GROOVY-10232
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit a1feedfe8e7bab039a004810cb3edb516af8c44b
Author: Daniel Sun <[email protected]>
AuthorDate: Sat Oct 23 17:51:16 2021 +0800

    GROOVY-10232: Massive increase in memory usage due to CacheableCallSite
---
 .../groovy/vmplugin/v8/CacheableCallSite.java      | 22 +++++++++++++++++++---
 1 file changed, 19 insertions(+), 3 deletions(-)

diff --git 
a/src/main/java/org/codehaus/groovy/vmplugin/v8/CacheableCallSite.java 
b/src/main/java/org/codehaus/groovy/vmplugin/v8/CacheableCallSite.java
index a6e4c4c..0e931fa 100644
--- a/src/main/java/org/codehaus/groovy/vmplugin/v8/CacheableCallSite.java
+++ b/src/main/java/org/codehaus/groovy/vmplugin/v8/CacheableCallSite.java
@@ -25,6 +25,7 @@ import org.codehaus.groovy.runtime.memoize.MemoizeCache;
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodType;
 import java.lang.invoke.MutableCallSite;
+import java.lang.ref.SoftReference;
 import java.util.concurrent.atomic.AtomicLong;
 
 /**
@@ -34,8 +35,8 @@ import java.util.concurrent.atomic.AtomicLong;
  */
 public class CacheableCallSite extends MutableCallSite {
     private static final int CACHE_SIZE = 
SystemUtil.getIntegerSafe("groovy.indy.callsite.cache.size", 16);
-    private final MemoizeCache<String, MethodHandleWrapper> cache = new 
LRUCache<>(CACHE_SIZE);
-    private volatile MethodHandleWrapper latestHitMethodHandleWrapper = null;
+    private volatile SoftReference<MemoizeCache<String, MethodHandleWrapper>> 
cacheSoftReference;
+    private volatile MethodHandleWrapper latestHitMethodHandleWrapper;
     private final AtomicLong fallbackCount = new AtomicLong(0);
     private MethodHandle defaultTarget;
     private MethodHandle fallbackTarget;
@@ -45,6 +46,7 @@ public class CacheableCallSite extends MutableCallSite {
     }
 
     public MethodHandleWrapper getAndPut(String className, 
MemoizeCache.ValueProvider<? super String, ? extends MethodHandleWrapper> 
valueProvider) {
+        final MemoizeCache<String, MethodHandleWrapper> cache = getCache();
         final MethodHandleWrapper result = cache.getAndPut(className, 
valueProvider);
         final MethodHandleWrapper lhmh = latestHitMethodHandleWrapper;
 
@@ -61,7 +63,7 @@ public class CacheableCallSite extends MutableCallSite {
     }
 
     public MethodHandleWrapper put(String name, MethodHandleWrapper mhw) {
-        return cache.put(name, mhw);
+        return getCache().put(name, mhw);
     }
 
     public long incrementFallbackCount() {
@@ -87,4 +89,18 @@ public class CacheableCallSite extends MutableCallSite {
     public void setFallbackTarget(MethodHandle fallbackTarget) {
         this.fallbackTarget = fallbackTarget;
     }
+
+    private MemoizeCache<String, MethodHandleWrapper> getCache() {
+        MemoizeCache<String, MethodHandleWrapper> cache;
+        SoftReference<MemoizeCache<String, MethodHandleWrapper>> ref = 
cacheSoftReference;
+        if (null == ref || null == (cache = ref.get())) {
+            synchronized (this) {
+                ref = cacheSoftReference;
+                if (null == ref || null == (cache = ref.get())) {
+                    this.cacheSoftReference = new SoftReference<>(cache = new 
LRUCache<>(CACHE_SIZE));
+                }
+            }
+        }
+        return cache;
+    }
 }

Reply via email to