Skip to content

Commit a43eaba

Browse files
committed
Move how fulfilled lazy call targets are handled
1 parent 1c925c7 commit a43eaba

File tree

2 files changed

+11
-13
lines changed

2 files changed

+11
-13
lines changed

src/main/java/org/truffleruby/language/methods/CachedLazyCallTargetSupplier.java

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,36 +9,32 @@
99
*/
1010
package org.truffleruby.language.methods;
1111

12-
import com.oracle.truffle.api.CompilerDirectives;
1312
import com.oracle.truffle.api.RootCallTarget;
1413

1514
import java.util.function.Supplier;
1615

1716
public class CachedLazyCallTargetSupplier {
1817

19-
private volatile RootCallTarget value = null;
18+
// Volatile, so that writes from another thread will finish publishing the RootCallTarget first
19+
private volatile RootCallTarget callTarget = null;
2020
private Supplier<RootCallTarget> supplier;
2121

2222
public CachedLazyCallTargetSupplier(Supplier<RootCallTarget> supplier) {
2323
this.supplier = supplier;
2424
}
2525

2626
public RootCallTarget get() {
27-
if (isAvailable()) {
28-
return value;
29-
}
30-
CompilerDirectives.transferToInterpreterAndInvalidate();
3127
synchronized (this) {
32-
if (value == null) {
33-
value = supplier.get();
28+
if (callTarget == null) {
29+
callTarget = supplier.get();
3430
supplier = null;
3531
}
36-
return value;
32+
return callTarget;
3733
}
3834
}
3935

40-
public boolean isAvailable() {
41-
return value != null;
36+
public RootCallTarget getWhenAvailable() {
37+
return callTarget;
4238
}
4339

4440
}

src/main/java/org/truffleruby/language/methods/InternalMethod.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
import java.util.Set;
1313

14+
import com.oracle.truffle.api.CompilerDirectives;
1415
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
1516
import com.oracle.truffle.api.dsl.NodeFactory;
1617
import org.truffleruby.RubyContext;
@@ -172,8 +173,8 @@ private InternalMethod(
172173

173174
/* If the call target supplier has already been run, then don't wait until the first time the InternalMethod is
174175
* asked for the call target, because this would be a deoptimization in getCallTarget(). */
175-
if (callTarget == null && callTargetSupplier != null && callTargetSupplier.isAvailable()) {
176-
this.callTarget = callTargetSupplier.get();
176+
if (callTarget == null && callTargetSupplier != null) {
177+
this.callTarget = callTargetSupplier.getWhenAvailable();
177178
}
178179
}
179180

@@ -231,6 +232,7 @@ public RubyProc getProc() {
231232

232233
public RootCallTarget getCallTarget() {
233234
if (callTarget == null) {
235+
CompilerDirectives.transferToInterpreterAndInvalidate();
234236
callTarget = callTargetSupplier.get();
235237
assert RubyRootNode.of(callTarget).getSharedMethodInfo() == sharedMethodInfo;
236238
}

0 commit comments

Comments
 (0)