Skip to content

Commit 104a3f5

Browse files
committed
Remove usages of AtomicBoolean.
1 parent 6b579e5 commit 104a3f5

File tree

4 files changed

+153
-75
lines changed

4 files changed

+153
-75
lines changed

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

Lines changed: 54 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
import java.util.Set;
3131
import java.util.concurrent.ConcurrentHashMap;
3232
import java.util.concurrent.ConcurrentMap;
33-
import java.util.concurrent.atomic.AtomicBoolean;
33+
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
3434
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
3535

3636
import org.graalvm.compiler.debug.GraalError;
@@ -58,6 +58,24 @@ public abstract class AnalysisField extends AnalysisElement implements ResolvedJ
5858
private static final AtomicReferenceFieldUpdater<AnalysisField, Object> OBSERVERS_UPDATER = //
5959
AtomicReferenceFieldUpdater.newUpdater(AnalysisField.class, Object.class, "observers");
6060

61+
private static final AtomicIntegerFieldUpdater<AnalysisField> isAccessedUpdater = AtomicIntegerFieldUpdater
62+
.newUpdater(AnalysisField.class, "isAccessed");
63+
64+
private static final AtomicIntegerFieldUpdater<AnalysisField> isReadUpdater = AtomicIntegerFieldUpdater
65+
.newUpdater(AnalysisField.class, "isRead");
66+
67+
private static final AtomicIntegerFieldUpdater<AnalysisField> isWrittenUpdater = AtomicIntegerFieldUpdater
68+
.newUpdater(AnalysisField.class, "isWritten");
69+
70+
private static final AtomicIntegerFieldUpdater<AnalysisField> isFoldedUpdater = AtomicIntegerFieldUpdater
71+
.newUpdater(AnalysisField.class, "isFolded");
72+
73+
private static final AtomicIntegerFieldUpdater<AnalysisField> isUnsafeAccessedUpdater = AtomicIntegerFieldUpdater
74+
.newUpdater(AnalysisField.class, "isUnsafeAccessed");
75+
76+
private static final AtomicIntegerFieldUpdater<AnalysisField> unsafeFrozenTypeStateUpdater = AtomicIntegerFieldUpdater
77+
.newUpdater(AnalysisField.class, "unsafeFrozenTypeState");
78+
6179
private final int id;
6280

6381
public final ResolvedJavaField wrapped;
@@ -74,15 +92,15 @@ public abstract class AnalysisField extends AnalysisElement implements ResolvedJ
7492
*/
7593
private ContextInsensitiveFieldTypeFlow instanceFieldFlow;
7694

77-
private AtomicBoolean isAccessed = new AtomicBoolean();
78-
private AtomicBoolean isRead = new AtomicBoolean();
79-
private AtomicBoolean isWritten = new AtomicBoolean();
80-
private AtomicBoolean isFolded = new AtomicBoolean();
95+
@SuppressWarnings("unused") private volatile int isAccessed;
96+
@SuppressWarnings("unused") private volatile int isRead;
97+
@SuppressWarnings("unused") private volatile int isWritten;
98+
@SuppressWarnings("unused") private volatile int isFolded;
8199

82100
private boolean isJNIAccessed;
83101
private boolean isUsedInComparison;
84-
private AtomicBoolean isUnsafeAccessed;
85-
private AtomicBoolean unsafeFrozenTypeState;
102+
@SuppressWarnings("unused") private volatile int isUnsafeAccessed;
103+
@SuppressWarnings("unused") private volatile int unsafeFrozenTypeState;
86104
@SuppressWarnings("unused") private volatile Object observers;
87105

88106
/**
@@ -106,8 +124,6 @@ public AnalysisField(AnalysisUniverse universe, ResolvedJavaField wrappedField)
106124
assert !wrappedField.isInternal();
107125

108126
this.position = -1;
109-
this.isUnsafeAccessed = new AtomicBoolean();
110-
this.unsafeFrozenTypeState = new AtomicBoolean();
111127

112128
this.wrapped = wrappedField;
113129
this.id = universe.nextFieldId.getAndIncrement();
@@ -153,30 +169,30 @@ private static AnalysisType getDeclaredType(AnalysisUniverse universe, ResolvedJ
153169
}
154170

155171
public void copyAccessInfos(AnalysisField other) {
156-
this.isAccessed = new AtomicBoolean(other.isAccessed.get());
157-
this.isUnsafeAccessed = other.isUnsafeAccessed;
172+
isAccessedUpdater.set(this, other.isAccessed);
173+
isUnsafeAccessedUpdater.set(this, other.isUnsafeAccessed);
158174
this.canBeNull = other.canBeNull;
159-
this.isWritten = new AtomicBoolean(other.isWritten.get());
160-
this.isFolded = new AtomicBoolean(other.isFolded.get());
161-
this.isRead = new AtomicBoolean(other.isRead.get());
175+
isWrittenUpdater.set(this, other.isWritten);
176+
isFoldedUpdater.set(this, other.isFolded);
177+
isReadUpdater.set(this, other.isRead);
162178
notifyUpdateAccessInfo();
163179
}
164180

165181
public void intersectAccessInfos(AnalysisField other) {
166-
this.isAccessed = new AtomicBoolean(this.isAccessed.get() && other.isAccessed.get());
182+
isAccessedUpdater.set(this, this.isAccessed & other.isAccessed);
167183
this.canBeNull = this.canBeNull && other.canBeNull;
168-
this.isWritten = new AtomicBoolean(this.isWritten.get() && other.isWritten.get());
169-
this.isFolded = new AtomicBoolean(this.isFolded.get() && other.isFolded.get());
170-
this.isRead = new AtomicBoolean(this.isRead.get() && other.isRead.get());
184+
isWrittenUpdater.set(this, this.isWritten & other.isWritten);
185+
isFoldedUpdater.set(this, this.isFolded & other.isFolded);
186+
isReadUpdater.set(this, this.isRead & other.isRead);
171187
notifyUpdateAccessInfo();
172188
}
173189

174190
public void clearAccessInfos() {
175-
this.isAccessed.set(false);
191+
isAccessedUpdater.set(this, 0);
176192
this.canBeNull = true;
177-
this.isWritten.set(false);
178-
this.isFolded.set(false);
179-
this.isRead.set(false);
193+
isWrittenUpdater.set(this, 0);
194+
isFoldedUpdater.set(this, 0);
195+
isReadUpdater.set(this, 0);
180196
notifyUpdateAccessInfo();
181197
}
182198

@@ -239,7 +255,7 @@ public void cleanupAfterAnalysis() {
239255
}
240256

241257
public boolean registerAsAccessed() {
242-
boolean firstAttempt = AtomicUtils.atomicMark(isAccessed);
258+
boolean firstAttempt = AtomicUtils.atomicMark(this, isAccessedUpdater);
243259
notifyUpdateAccessInfo();
244260
if (firstAttempt) {
245261
onReachable();
@@ -250,7 +266,7 @@ public boolean registerAsAccessed() {
250266
}
251267

252268
public boolean registerAsRead(MethodTypeFlow method) {
253-
boolean firstAttempt = AtomicUtils.atomicMark(isRead);
269+
boolean firstAttempt = AtomicUtils.atomicMark(this, isReadUpdater);
254270
notifyUpdateAccessInfo();
255271
if (readBy != null && method != null) {
256272
readBy.put(method, Boolean.TRUE);
@@ -270,7 +286,7 @@ public boolean registerAsRead(MethodTypeFlow method) {
270286
* for an unsafe accessed field.
271287
*/
272288
public boolean registerAsWritten(MethodTypeFlow method) {
273-
boolean firstAttempt = AtomicUtils.atomicMark(isWritten);
289+
boolean firstAttempt = AtomicUtils.atomicMark(this, isWrittenUpdater);
274290
notifyUpdateAccessInfo();
275291
if (writtenBy != null && method != null) {
276292
writtenBy.put(method, Boolean.TRUE);
@@ -285,7 +301,7 @@ public boolean registerAsWritten(MethodTypeFlow method) {
285301
}
286302

287303
public void markFolded() {
288-
if (AtomicUtils.atomicMark(isFolded)) {
304+
if (AtomicUtils.atomicMark(this, isFoldedUpdater)) {
289305
getDeclaringClass().registerAsReachable();
290306
onReachable();
291307
}
@@ -305,9 +321,9 @@ public void registerAsUnsafeAccessed(UnsafePartitionKind partitionKind) {
305321
* only register fields as unsafe accessed with their declaring type once.
306322
*/
307323

308-
if (!isUnsafeAccessed.getAndSet(true)) {
324+
if (isUnsafeAccessedUpdater.getAndSet(this, 1) != 1) {
309325
/*
310-
* The atomic boolean ensures that the field is registered as unsafe accessed with its
326+
* The atomic updater ensures that the field is registered as unsafe accessed with its
311327
* declaring class only once. However, at the end of this call the registration might
312328
* still be in progress. The first thread that calls this methods enters the if and
313329
* starts the registration, the next threads return right away, while the registration
@@ -329,7 +345,7 @@ public void registerAsUnsafeAccessed(UnsafePartitionKind partitionKind) {
329345
}
330346

331347
public boolean isUnsafeAccessed() {
332-
return isUnsafeAccessed.get();
348+
return AtomicUtils.isSet(this, isUnsafeAccessedUpdater);
333349
}
334350

335351
public void registerAsJNIAccessed() {
@@ -341,11 +357,11 @@ public boolean isJNIAccessed() {
341357
}
342358

343359
public void setUnsafeFrozenTypeState(boolean value) {
344-
unsafeFrozenTypeState.getAndSet(value);
360+
unsafeFrozenTypeStateUpdater.set(this, value ? 1 : 0);
345361
}
346362

347363
public boolean hasUnsafeFrozenTypeState() {
348-
return unsafeFrozenTypeState.get();
364+
return AtomicUtils.isSet(this, unsafeFrozenTypeStateUpdater);
349365
}
350366

351367
public Set<MethodTypeFlow> getReadBy() {
@@ -376,24 +392,26 @@ public Set<MethodTypeFlow> getWrittenBy() {
376392
* DirectByteBuffer remains reachable.
377393
*/
378394
public boolean isAccessed() {
379-
return isAccessed.get() || isRead.get() || (isWritten.get() && (Modifier.isVolatile(getModifiers()) || getStorageKind() == JavaKind.Object));
395+
return AtomicUtils.isSet(this, isAccessedUpdater) || AtomicUtils.isSet(this, isReadUpdater) ||
396+
(AtomicUtils.isSet(this, isWrittenUpdater) && (Modifier.isVolatile(getModifiers()) || getStorageKind() == JavaKind.Object));
380397
}
381398

382399
public boolean isRead() {
383-
return isAccessed.get() || isRead.get();
400+
return AtomicUtils.isSet(this, isAccessedUpdater) || AtomicUtils.isSet(this, isReadUpdater);
384401
}
385402

386403
public boolean isWritten() {
387-
return isAccessed.get() || isWritten.get();
404+
return AtomicUtils.isSet(this, isAccessedUpdater) || AtomicUtils.isSet(this, isWrittenUpdater);
388405
}
389406

390407
public boolean isFolded() {
391-
return isFolded.get();
408+
return AtomicUtils.isSet(this, isFoldedUpdater);
392409
}
393410

394411
@Override
395412
public boolean isReachable() {
396-
return isAccessed.get() || isRead.get() || isWritten.get() || isFolded.get();
413+
return AtomicUtils.isSet(this, isAccessedUpdater) || AtomicUtils.isSet(this, isReadUpdater) ||
414+
AtomicUtils.isSet(this, isWrittenUpdater) || AtomicUtils.isSet(this, isFoldedUpdater);
397415
}
398416

399417
@Override

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

Lines changed: 39 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
import java.lang.reflect.Type;
3434
import java.util.List;
3535
import java.util.Set;
36-
import java.util.concurrent.atomic.AtomicBoolean;
36+
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
3737
import java.util.concurrent.atomic.AtomicReference;
3838
import java.util.concurrent.locks.ReentrantLock;
3939
import java.util.stream.Collectors;
@@ -74,6 +74,24 @@
7474

7575
public abstract class AnalysisMethod extends AnalysisElement implements WrappedJavaMethod, GraphProvider, OriginalMethodProvider {
7676

77+
private static final AtomicIntegerFieldUpdater<AnalysisMethod> isVirtualRootMethodUpdater = AtomicIntegerFieldUpdater
78+
.newUpdater(AnalysisMethod.class, "isVirtualRootMethod");
79+
80+
private static final AtomicIntegerFieldUpdater<AnalysisMethod> isDirectRootMethodUpdater = AtomicIntegerFieldUpdater
81+
.newUpdater(AnalysisMethod.class, "isDirectRootMethod");
82+
83+
private static final AtomicIntegerFieldUpdater<AnalysisMethod> isInvokedUpdater = AtomicIntegerFieldUpdater
84+
.newUpdater(AnalysisMethod.class, "isInvoked");
85+
86+
private static final AtomicIntegerFieldUpdater<AnalysisMethod> isImplementationInvokedUpdater = AtomicIntegerFieldUpdater
87+
.newUpdater(AnalysisMethod.class, "isImplementationInvoked");
88+
89+
private static final AtomicIntegerFieldUpdater<AnalysisMethod> isIntrinsicMethodUpdater = AtomicIntegerFieldUpdater
90+
.newUpdater(AnalysisMethod.class, "isIntrinsicMethod");
91+
92+
private static final AtomicIntegerFieldUpdater<AnalysisMethod> isInlinedUpdater = AtomicIntegerFieldUpdater
93+
.newUpdater(AnalysisMethod.class, "isInlined");
94+
7795
public final ResolvedJavaMethod wrapped;
7896

7997
private final int id;
@@ -85,14 +103,14 @@ public abstract class AnalysisMethod extends AnalysisElement implements WrappedJ
85103
private final AnalysisType declaringClass;
86104

87105
/** Virtually invoked method registered as root. */
88-
private final AtomicBoolean isVirtualRootMethod = new AtomicBoolean();
106+
@SuppressWarnings("unused") private volatile int isVirtualRootMethod;
89107
/** Direct (special or static) invoked method registered as root. */
90-
private final AtomicBoolean isDirectRootMethod = new AtomicBoolean();
108+
@SuppressWarnings("unused") private volatile int isDirectRootMethod;
91109
private Object entryPointData;
92-
private final AtomicBoolean isInvoked = new AtomicBoolean();
93-
private final AtomicBoolean isImplementationInvoked = new AtomicBoolean();
94-
private final AtomicBoolean isIntrinsicMethod = new AtomicBoolean();
95-
private final AtomicBoolean isInlined = new AtomicBoolean();
110+
@SuppressWarnings("unused") private volatile int isInvoked;
111+
@SuppressWarnings("unused") private volatile int isImplementationInvoked;
112+
@SuppressWarnings("unused") private volatile int isIntrinsicMethod;
113+
@SuppressWarnings("unused") private volatile int isInlined;
96114

97115
private final AtomicReference<Object> parsedGraphCacheState = new AtomicReference<>(GRAPH_CACHE_UNPARSED);
98116
private static final Object GRAPH_CACHE_UNPARSED = "unparsed";
@@ -204,7 +222,7 @@ public int getId() {
204222
* resolution must be able to find the method (otherwise the intrinsification would not work).
205223
*/
206224
public void registerAsIntrinsicMethod() {
207-
AtomicUtils.atomicMarkAndRun(isIntrinsicMethod, this::onReachable);
225+
AtomicUtils.atomicMarkAndRun(this, isIntrinsicMethodUpdater, this::onReachable);
208226
}
209227

210228
public void registerAsEntryPoint(Object newEntryPointData) {
@@ -218,7 +236,7 @@ public void registerAsEntryPoint(Object newEntryPointData) {
218236
}
219237

220238
public boolean registerAsInvoked() {
221-
return AtomicUtils.atomicMark(isInvoked);
239+
return AtomicUtils.atomicMark(this, isInvokedUpdater);
222240
}
223241

224242
public boolean registerAsImplementationInvoked() {
@@ -233,11 +251,11 @@ public boolean registerAsImplementationInvoked() {
233251
* return before the class gets marked as reachable.
234252
*/
235253
getDeclaringClass().registerAsReachable();
236-
return AtomicUtils.atomicMarkAndRun(isImplementationInvoked, this::onReachable);
254+
return AtomicUtils.atomicMarkAndRun(this, isImplementationInvokedUpdater, this::onReachable);
237255
}
238256

239257
public void registerAsInlined() {
240-
AtomicUtils.atomicMarkAndRun(isInlined, this::onReachable);
258+
AtomicUtils.atomicMarkAndRun(this, isInlinedUpdater, this::onReachable);
241259
}
242260

243261
/** Get the set of all callers for this method, as inferred by the static analysis. */
@@ -257,7 +275,7 @@ public Object getEntryPointData() {
257275
}
258276

259277
public boolean isIntrinsicMethod() {
260-
return isIntrinsicMethod.get();
278+
return AtomicUtils.isSet(this, isIntrinsicMethodUpdater);
261279
}
262280

263281
/**
@@ -271,15 +289,15 @@ public boolean isIntrinsicMethod() {
271289
*/
272290
public boolean registerAsVirtualRootMethod() {
273291
getDeclaringClass().registerAsReachable();
274-
return AtomicUtils.atomicMark(isVirtualRootMethod);
292+
return AtomicUtils.atomicMark(this, isVirtualRootMethodUpdater);
275293
}
276294

277295
/**
278296
* Registers this method as a direct (special or static) root for the analysis.
279297
*/
280298
public boolean registerAsDirectRootMethod() {
281299
getDeclaringClass().registerAsReachable();
282-
return AtomicUtils.atomicMark(isDirectRootMethod);
300+
return AtomicUtils.atomicMark(this, isDirectRootMethodUpdater);
283301
}
284302

285303
/**
@@ -288,7 +306,7 @@ public boolean registerAsDirectRootMethod() {
288306
* receiver types.
289307
*/
290308
public boolean isVirtualRootMethod() {
291-
return isVirtualRootMethod.get();
309+
return AtomicUtils.isSet(this, isVirtualRootMethodUpdater);
292310
}
293311

294312
/**
@@ -298,35 +316,35 @@ public boolean isVirtualRootMethod() {
298316
* implementation-invoked too.
299317
*/
300318
public boolean isDirectRootMethod() {
301-
return isDirectRootMethod.get();
319+
return AtomicUtils.isSet(this, isDirectRootMethodUpdater);
302320
}
303321

304322
public boolean isSimplyInvoked() {
305-
return isInvoked.get();
323+
return AtomicUtils.isSet(this, isInvokedUpdater);
306324
}
307325

308326
public boolean isSimplyImplementationInvoked() {
309-
return isImplementationInvoked.get();
327+
return AtomicUtils.isSet(this, isImplementationInvokedUpdater);
310328
}
311329

312330
/**
313331
* Returns true if this method is ever used as the target of a call site.
314332
*/
315333
public boolean isInvoked() {
316-
return isIntrinsicMethod.get() || isVirtualRootMethod() || isDirectRootMethod() || isInvoked.get();
334+
return isIntrinsicMethod() || isVirtualRootMethod() || isDirectRootMethod() || AtomicUtils.isSet(this, isInvokedUpdater);
317335
}
318336

319337
/**
320338
* Returns true if the method body can ever be executed. Methods registered as root are also
321339
* registered as implementation invoked when they are linked.
322340
*/
323341
public boolean isImplementationInvoked() {
324-
return !Modifier.isAbstract(getModifiers()) && (isIntrinsicMethod.get() || isImplementationInvoked.get());
342+
return !Modifier.isAbstract(getModifiers()) && (isIntrinsicMethod() || AtomicUtils.isSet(this, isImplementationInvokedUpdater));
325343
}
326344

327345
@Override
328346
public boolean isReachable() {
329-
return isImplementationInvoked() || isInlined.get();
347+
return isImplementationInvoked() || AtomicUtils.isSet(this, isInlinedUpdater);
330348
}
331349

332350
@Override

0 commit comments

Comments
 (0)