You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2022/12/04 10:57:51 UTC

[groovy] branch GROOVY_4_0_X updated: GROOVY-10772: Hold `MethodHandleWrapper` with `SoftReference` in cache

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

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


The following commit(s) were added to refs/heads/GROOVY_4_0_X by this push:
     new 542d64de24 GROOVY-10772: Hold `MethodHandleWrapper` with `SoftReference` in cache
542d64de24 is described below

commit 542d64de24fa58974eab0d4dde1822b067ae14dc
Author: Daniel Sun <su...@apache.org>
AuthorDate: Sun Dec 4 18:05:01 2022 +0800

    GROOVY-10772: Hold `MethodHandleWrapper` with `SoftReference` in cache
    
    (cherry picked from commit 1cac5bf86e5d72b90545cb8766b4b05cb125ac4a)
---
 .../groovy/vmplugin/v8/CacheableCallSite.java      | 36 +++++++++++++++++++---
 1 file changed, 31 insertions(+), 5 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 aaa7138dbe..f998dd781e 100644
--- a/src/main/java/org/codehaus/groovy/vmplugin/v8/CacheableCallSite.java
+++ b/src/main/java/org/codehaus/groovy/vmplugin/v8/CacheableCallSite.java
@@ -24,6 +24,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.LinkedHashMap;
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicLong;
@@ -41,8 +42,8 @@ public class CacheableCallSite extends MutableCallSite {
     private final AtomicLong fallbackCount = new AtomicLong();
     private MethodHandle defaultTarget;
     private MethodHandle fallbackTarget;
-    private final Map<String, MethodHandleWrapper> lruCache =
-            new LinkedHashMap<String, MethodHandleWrapper>(INITIAL_CAPACITY, LOAD_FACTOR, true) {
+    private final Map<String, SoftReference<MethodHandleWrapper>> lruCache =
+            new LinkedHashMap<>(INITIAL_CAPACITY, LOAD_FACTOR, true) {
                 private static final long serialVersionUID = 7785958879964294463L;
 
                 @Override
@@ -56,9 +57,21 @@ public class CacheableCallSite extends MutableCallSite {
     }
 
     public MethodHandleWrapper getAndPut(String className, MemoizeCache.ValueProvider<? super String, ? extends MethodHandleWrapper> valueProvider) {
-        final MethodHandleWrapper result;
+        MethodHandleWrapper result = null;
         synchronized (lruCache) {
-            result = lruCache.computeIfAbsent(className, valueProvider::provide);
+            final SoftReference<MethodHandleWrapper> methodHandleWrapperSoftReference = lruCache.get(className);
+            if (null != methodHandleWrapperSoftReference) {
+                result = methodHandleWrapperSoftReference.get();
+
+                if (null == result) {
+                    removeAllStaleEntriesOfLruCache();
+                }
+            }
+
+            if (null == result) {
+                result = valueProvider.provide(className);
+                lruCache.put(className, new SoftReference<>(result));
+            }
         }
         final MethodHandleWrapper lhmh = latestHitMethodHandleWrapper;
 
@@ -76,10 +89,23 @@ public class CacheableCallSite extends MutableCallSite {
 
     public MethodHandleWrapper put(String name, MethodHandleWrapper mhw) {
         synchronized (lruCache) {
-            return lruCache.put(name, mhw);
+            final SoftReference<MethodHandleWrapper> methodHandleWrapperSoftReference;
+            methodHandleWrapperSoftReference = lruCache.put(name, new SoftReference<>(mhw));
+            if (null == methodHandleWrapperSoftReference) {
+                return null;
+            }
+            final MethodHandleWrapper methodHandleWrapper = methodHandleWrapperSoftReference.get();
+            if (null == methodHandleWrapper) {
+                removeAllStaleEntriesOfLruCache();
+            }
+            return methodHandleWrapper;
         }
     }
 
+    private void removeAllStaleEntriesOfLruCache() {
+        lruCache.values().removeIf(v -> null == v.get());
+    }
+
     public long incrementFallbackCount() {
         return fallbackCount.incrementAndGet();
     }