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 2025/05/24 02:40:28 UTC

(groovy) branch GROOVY-11640 created (now 40853a053a)

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

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


      at 40853a053a GROOVY-11640: GC pause by Metadata GC Threshold for weeks then turned to Full GC

This branch includes the following new commits:

     new 40853a053a GROOVY-11640: GC pause by Metadata GC Threshold for weeks then turned to Full GC

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



(groovy) 01/01: GROOVY-11640: GC pause by Metadata GC Threshold for weeks then turned to Full GC

Posted by su...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 40853a053a9b0bed3c6fa97cc771d73f2c43e395
Author: Daniel Sun <su...@apache.org>
AuthorDate: Sat May 24 11:37:44 2025 +0900

    GROOVY-11640: GC pause by Metadata GC Threshold for weeks then turned to Full GC
---
 .../org/codehaus/groovy/vmplugin/v8/CacheableCallSite.java  |  6 ++++++
 .../java/org/codehaus/groovy/vmplugin/v8/IndyInterface.java | 13 +++++++++++--
 2 files changed, 17 insertions(+), 2 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 58a6dfac5f..e93e423633 100644
--- a/src/main/java/org/codehaus/groovy/vmplugin/v8/CacheableCallSite.java
+++ b/src/main/java/org/codehaus/groovy/vmplugin/v8/CacheableCallSite.java
@@ -47,6 +47,7 @@ public class CacheableCallSite extends MutableCallSite {
     private final MethodHandles.Lookup lookup;
     private volatile SoftReference<MethodHandleWrapper> latestHitMethodHandleWrapperSoftReference = null;
     private final AtomicLong fallbackCount = new AtomicLong();
+    private final AtomicLong fallbackRound = new AtomicLong();
     private MethodHandle defaultTarget;
     private MethodHandle fallbackTarget;
     private final Map<String, SoftReference<MethodHandleWrapper>> lruCache =
@@ -119,6 +120,11 @@ public class CacheableCallSite extends MutableCallSite {
 
     public void resetFallbackCount() {
         fallbackCount.set(0);
+        fallbackRound.incrementAndGet();
+    }
+
+    public AtomicLong getFallbackRound() {
+        return fallbackRound;
     }
 
     public MethodHandle getDefaultTarget() {
diff --git a/src/main/java/org/codehaus/groovy/vmplugin/v8/IndyInterface.java b/src/main/java/org/codehaus/groovy/vmplugin/v8/IndyInterface.java
index 606328a1ea..b14dfd94e3 100644
--- a/src/main/java/org/codehaus/groovy/vmplugin/v8/IndyInterface.java
+++ b/src/main/java/org/codehaus/groovy/vmplugin/v8/IndyInterface.java
@@ -50,6 +50,8 @@ import java.util.stream.Stream;
 public class IndyInterface {
     private static final long INDY_OPTIMIZE_THRESHOLD = SystemUtil.getLongSafe("groovy.indy.optimize.threshold", 10_000L);
     private static final long INDY_FALLBACK_THRESHOLD = SystemUtil.getLongSafe("groovy.indy.fallback.threshold", 10_000L);
+    private static final long INDY_FALLBACK_CUTOFF = SystemUtil.getLongSafe("groovy.indy.fallback.cutoff", 100L);
+
 
     /**
      * flags for method and property calls
@@ -327,8 +329,15 @@ public class IndyInterface {
         }
 
         if (mhw.isCanSetTarget() && (callSite.getTarget() != mhw.getTargetMethodHandle()) && (mhw.getLatestHitCount() > INDY_OPTIMIZE_THRESHOLD)) {
-            callSite.setTarget(mhw.getTargetMethodHandle());
-            if (LOG_ENABLED) LOG.info("call site target set, preparing outside invocation");
+            if (callSite.getFallbackRound().get() > INDY_FALLBACK_CUTOFF) {
+                if (callSite.getTarget() != callSite.getDefaultTarget()) {
+                    // reset the call site target to default forever to avoid JIT optimizing and deoptimizing frequently
+                    callSite.setTarget(callSite.getDefaultTarget());
+                }
+            } else {
+                callSite.setTarget(mhw.getTargetMethodHandle());
+                if (LOG_ENABLED) LOG.info("call site target set, preparing outside invocation");
+            }
 
             mhw.resetLatestHitCount();
         }