4242import static com .oracle .truffle .espresso .classfile .Constants .REF_invokeVirtual ;
4343
4444import java .io .PrintStream ;
45+ import java .lang .invoke .VarHandle ;
4546import java .lang .reflect .Modifier ;
4647import java .util .ArrayList ;
4748import java .util .Arrays ;
@@ -1076,6 +1077,7 @@ public final class MethodVersion implements MethodRef, ModifiersProvider {
10761077 private final ExceptionsAttribute exceptionsAttribute ;
10771078
10781079 @ CompilationFinal private CallTarget callTarget ;
1080+ @ CompilationFinal private CallTarget callTargetNoSubstitutions ;
10791081
10801082 @ CompilationFinal private int vtableIndex = -1 ;
10811083 @ CompilationFinal private int itableIndex = -1 ;
@@ -1228,11 +1230,22 @@ public RuntimeConstantPool getPool() {
12281230 return pool ;
12291231 }
12301232
1233+ @ SuppressFBWarnings (value = "DC_DOUBLECHECK" , //
1234+ justification = "Publication uses a release fence, assuming data dependency ordering on the reader side." )
12311235 private CallTarget getCallTargetNoSubstitution () {
12321236 CompilerAsserts .neverPartOfCompilation ();
12331237 EspressoError .guarantee (getSubstitutions ().hasSubstitutionFor (getMethod ()),
12341238 "Using 'getCallTargetNoSubstitution' should be done only to bypass the substitution mechanism." );
1235- return findCallTarget ();
1239+ if (callTargetNoSubstitutions == null ) {
1240+ synchronized (this ) {
1241+ if (callTargetNoSubstitutions == null ) {
1242+ CallTarget target = findCallTarget ();
1243+ VarHandle .releaseFence ();
1244+ callTargetNoSubstitutions = target ;
1245+ }
1246+ }
1247+ }
1248+ return callTargetNoSubstitutions ;
12361249 }
12371250
12381251 public CallTarget getCallTarget () {
@@ -1253,26 +1266,26 @@ private void resolveCallTarget() {
12531266 if (callTarget != null ) {
12541267 return ;
12551268 }
1269+ CallTarget target ;
12561270 if (proxy != Method .this ) {
1257- this .callTarget = proxy .getCallTarget ();
1258- return ;
1259- }
1260-
1261- /*
1262- * The substitution factory does the validation e.g. some substitutions only apply
1263- * for classes/methods in the boot or platform class loaders. A warning is logged if
1264- * the validation fails.
1265- */
1266- EspressoRootNode redirectedMethod = getSubstitutions ().get (getMethod ());
1267- if (redirectedMethod != null ) {
1268- callTarget = redirectedMethod .getCallTarget ();
1269- return ;
1271+ target = proxy .getCallTarget ();
1272+ } else {
1273+ /*
1274+ * The substitution factory does the validation e.g. some substitutions only
1275+ * apply for classes/methods in the boot or platform class loaders. A warning is
1276+ * logged if the validation fails.
1277+ */
1278+ EspressoRootNode redirectedMethod = getSubstitutions ().get (getMethod ());
1279+ if (redirectedMethod != null ) {
1280+ target = redirectedMethod .getCallTarget ();
1281+ } else {
1282+ assert callTargetNoSubstitutions == null ;
1283+ target = findCallTarget ();
1284+ }
12701285 }
1271-
1272- CallTarget target = findCallTarget ();
12731286 if (target != null ) {
1287+ VarHandle .releaseFence ();
12741288 callTarget = target ;
1275- return ;
12761289 }
12771290 }
12781291 }
0 commit comments