Skip to content

Commit dff4299

Browse files
committed
ensure a unique fallback method is created for a given method
1 parent 24f5a78 commit dff4299

File tree

1 file changed

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

1 file changed

+37
-3
lines changed

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

Lines changed: 37 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,16 @@ 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+
newResolvedMethod = getUniverse().getBigbang().fallbackResolveConcreteMethod(this, (AnalysisMethod) method);
1142+
}
11321143
}
11331144

11341145
} catch (UnsupportedFeatureException e) {
@@ -1140,9 +1151,32 @@ public AnalysisMethod resolveConcreteMethod(ResolvedJavaMethod method, ResolvedJ
11401151
if (newResolvedMethod == null) {
11411152
newResolvedMethod = NULL_METHOD;
11421153
}
1143-
Object oldResolvedMethod = resolvedMethods.putIfAbsent(method, newResolvedMethod);
1144-
resolvedMethod = oldResolvedMethod != null ? oldResolvedMethod : newResolvedMethod;
1154+
1155+
if (computingFallback) {
1156+
/*
1157+
* If computingFallback is set, it is this thread's responsibility to install the
1158+
* result and override the placeholder put in the map.
1159+
*/
1160+
var finalResolvedMethod = newResolvedMethod;
1161+
resolvedMethods.compute(method, (k, v) -> {
1162+
assert v == COMPUTING_FALLBACK_RESOLUTION : v;
1163+
return finalResolvedMethod;
1164+
});
1165+
resolvedMethod = newResolvedMethod;
1166+
} else {
1167+
Object oldResolvedMethod = resolvedMethods.putIfAbsent(method, newResolvedMethod);
1168+
resolvedMethod = oldResolvedMethod != null ? oldResolvedMethod : newResolvedMethod;
1169+
}
1170+
}
1171+
1172+
/*
1173+
* Wait for fallback resolution computation to complete on another thread (if needed).
1174+
*/
1175+
while (resolvedMethod == COMPUTING_FALLBACK_RESOLUTION) {
1176+
Thread.onSpinWait();
1177+
resolvedMethod = resolvedMethods.get(method);
11451178
}
1179+
assert resolvedMethod != null;
11461180
return resolvedMethod == NULL_METHOD ? null : (AnalysisMethod) resolvedMethod;
11471181
}
11481182

0 commit comments

Comments
 (0)