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 fdfdf3968eab838cbf74af4d5a04dd42588de854 Author: Daniel Sun <[email protected]> AuthorDate: Sat May 24 17:43:42 2025 +0900 GROOVY-11640: GC pause by Metadata GC Threshold for weeks then turned to Full GC --- .../codehaus/groovy/vmplugin/v8/CacheableCallSite.java | 6 ++++++ .../org/codehaus/groovy/vmplugin/v8/IndyInterface.java | 16 ++++++++++++---- 2 files changed, 18 insertions(+), 4 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..d17fca15fe 100644 --- a/src/main/java/org/codehaus/groovy/vmplugin/v8/IndyInterface.java +++ b/src/main/java/org/codehaus/groovy/vmplugin/v8/IndyInterface.java @@ -48,8 +48,9 @@ import java.util.stream.Stream; * methods and classes. */ 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_OPTIMIZE_THRESHOLD = SystemUtil.getLongSafe("groovy.indy.optimize.threshold", 1_000L); + private static final long INDY_FALLBACK_THRESHOLD = SystemUtil.getLongSafe("groovy.indy.fallback.threshold", 1_000L); + private static final long INDY_FALLBACK_CUTOFF = SystemUtil.getLongSafe("groovy.indy.fallback.cutoff", 100L); /** * flags for method and property calls @@ -327,8 +328,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 deoptimization storm further + callSite.setTarget(callSite.getDefaultTarget()); + } + } else { + callSite.setTarget(mhw.getTargetMethodHandle()); + if (LOG_ENABLED) LOG.info("call site target set, preparing outside invocation"); + } mhw.resetLatestHitCount(); }
