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 d0c6c2f1a5f111319082cf6481dd07fd35753b61 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 | 8 +++++++- .../org/codehaus/groovy/vmplugin/v8/IndyInterface.java | 16 ++++++++++++---- 2 files changed, 19 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 58a6dfac5f..73527d5227 100644 --- a/src/main/java/org/codehaus/groovy/vmplugin/v8/CacheableCallSite.java +++ b/src/main/java/org/codehaus/groovy/vmplugin/v8/CacheableCallSite.java @@ -41,12 +41,13 @@ import java.util.logging.Logger; * @since 3.0.0 */ public class CacheableCallSite extends MutableCallSite { - private static final int CACHE_SIZE = SystemUtil.getIntegerSafe("groovy.indy.callsite.cache.size", 4); + private static final int CACHE_SIZE = SystemUtil.getIntegerSafe("groovy.indy.callsite.cache.size", 8); private static final float LOAD_FACTOR = 0.75f; private static final int INITIAL_CAPACITY = (int) Math.ceil(CACHE_SIZE / LOAD_FACTOR) + 1; 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(); }
