From 929fe3c9ca1c689f4b96175ea3e63f88c6fec8b0 Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Fri, 3 Nov 2023 13:39:53 -0500 Subject: [PATCH] Fix a race in indy global var caching The logic here acquires the Invalidator from the variable and uses that to guard the cached value. However, if this is a SwitchPoint invalidator (assumed by the code) then it replaces the SwitchPoint with a new one after invalidation. If we do not grab the actual SwitchPoint before the value, we may end up associating the current value with a newer SwitchPoint and never see the subsequent update. This is likely the main cause of intermittent global variable failures with indy global caching turned on. --- .../main/java/org/jruby/runtime/invokedynamic/GlobalSite.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/jruby/runtime/invokedynamic/GlobalSite.java b/core/src/main/java/org/jruby/runtime/invokedynamic/GlobalSite.java index b44bbf16819e..db84c093a64a 100644 --- a/core/src/main/java/org/jruby/runtime/invokedynamic/GlobalSite.java +++ b/core/src/main/java/org/jruby/runtime/invokedynamic/GlobalSite.java @@ -105,7 +105,7 @@ public IRubyObject getGlobalFallback(ThreadContext context) throws Throwable { return (IRubyObject)uncached.invokeWithArguments(context); } - Invalidator invalidator = variable.getInvalidator(); + SwitchPoint invalidator = (SwitchPoint) variable.getInvalidator().getData(); IRubyObject value = variable.getAccessor().getValue(); MethodHandle target = constant(IRubyObject.class, value); @@ -113,7 +113,7 @@ public IRubyObject getGlobalFallback(ThreadContext context) throws Throwable { MethodHandle fallback = lookup().findVirtual(GlobalSite.class, "getGlobalFallback", methodType(IRubyObject.class, ThreadContext.class)); fallback = fallback.bindTo(this); - target = ((SwitchPoint)invalidator.getData()).guardWithTest(target, fallback); + target = invalidator.guardWithTest(target, fallback); setTarget(target);