Skip to content

Commit 95bc812

Browse files
committed
[GR-58055] Ensure unique fallback methods.
PullRequest: graal/19293
2 parents a302974 + ad19703 commit 95bc812

File tree

1 file changed

+48
-3
lines changed
  • substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta

1 file changed

+48
-3
lines changed

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisType.java

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ public abstract class AnalysisType extends AnalysisElement implements WrappedJav
161161
* implement a method.
162162
*/
163163
private static final Object NULL_METHOD = new Object();
164+
private static final Object COMPUTING_FALLBACK_RESOLUTION = new Object();
164165

165166
private final AnalysisType componentType;
166167
private final AnalysisType elementalType;
@@ -1117,6 +1118,7 @@ public AnalysisMethod resolveConcreteMethod(ResolvedJavaMethod method, ResolvedJ
11171118
if (resolvedMethod == null) {
11181119
ResolvedJavaMethod originalMethod = OriginalMethodProvider.getOriginalMethod(method);
11191120
Object newResolvedMethod = null;
1121+
boolean computingFallback = false;
11201122
if (originalMethod != null) {
11211123
/*
11221124
* We do not want any access checks to be performed, so we use the method's
@@ -1128,7 +1130,27 @@ public AnalysisMethod resolveConcreteMethod(ResolvedJavaMethod method, ResolvedJ
11281130
var concreteMethod = originalMethod instanceof BaseLayerMethod ? originalMethod : wrapped.resolveConcreteMethod(originalMethod, originalCallerType);
11291131
newResolvedMethod = universe.lookup(concreteMethod);
11301132
if (newResolvedMethod == null) {
1131-
newResolvedMethod = getUniverse().getBigbang().fallbackResolveConcreteMethod(this, (AnalysisMethod) method);
1133+
/*
1134+
* Note we cannot directly use computeIfAbsent; calling
1135+
* fallbackResolveConcreteMethod will potentially cause other entries to be
1136+
* added to resolvedMethods, resulting in illegal recursive updates.
1137+
*/
1138+
Object oldResolvedMethod = resolvedMethods.putIfAbsent(method, COMPUTING_FALLBACK_RESOLUTION);
1139+
if (oldResolvedMethod == null) {
1140+
computingFallback = true;
1141+
try {
1142+
newResolvedMethod = getUniverse().getBigbang().fallbackResolveConcreteMethod(this, (AnalysisMethod) method);
1143+
} catch (Throwable t) {
1144+
/* Finalize result if an error occurs. */
1145+
resolvedMethods.compute(method, (k, v) -> {
1146+
assert v == COMPUTING_FALLBACK_RESOLUTION : v;
1147+
return NULL_METHOD;
1148+
});
1149+
computingFallback = false;
1150+
1151+
throw t;
1152+
}
1153+
}
11321154
}
11331155

11341156
} catch (UnsupportedFeatureException e) {
@@ -1140,9 +1162,32 @@ public AnalysisMethod resolveConcreteMethod(ResolvedJavaMethod method, ResolvedJ
11401162
if (newResolvedMethod == null) {
11411163
newResolvedMethod = NULL_METHOD;
11421164
}
1143-
Object oldResolvedMethod = resolvedMethods.putIfAbsent(method, newResolvedMethod);
1144-
resolvedMethod = oldResolvedMethod != null ? oldResolvedMethod : newResolvedMethod;
1165+
1166+
if (computingFallback) {
1167+
/*
1168+
* If computingFallback is set, it is this thread's responsibility to install the
1169+
* result and override the placeholder put in the map.
1170+
*/
1171+
var finalResolvedMethod = newResolvedMethod;
1172+
resolvedMethods.compute(method, (k, v) -> {
1173+
assert v == COMPUTING_FALLBACK_RESOLUTION : v;
1174+
return finalResolvedMethod;
1175+
});
1176+
resolvedMethod = newResolvedMethod;
1177+
} else {
1178+
Object oldResolvedMethod = resolvedMethods.putIfAbsent(method, newResolvedMethod);
1179+
resolvedMethod = oldResolvedMethod != null ? oldResolvedMethod : newResolvedMethod;
1180+
}
1181+
}
1182+
1183+
/*
1184+
* Wait for fallback resolution computation to complete on another thread (if needed).
1185+
*/
1186+
while (resolvedMethod == COMPUTING_FALLBACK_RESOLUTION) {
1187+
Thread.onSpinWait();
1188+
resolvedMethod = resolvedMethods.get(method);
11451189
}
1190+
assert resolvedMethod != null;
11461191
return resolvedMethod == NULL_METHOD ? null : (AnalysisMethod) resolvedMethod;
11471192
}
11481193

0 commit comments

Comments
 (0)