Skip to content

Commit 781eb02

Browse files
committed
[GR-43619] Refactor analysis: fix BitSet preallocation and cache options.
PullRequest: graal/13712
2 parents cf00101 + 1b04e6b commit 781eb02

File tree

7 files changed

+82
-45
lines changed

7 files changed

+82
-45
lines changed

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AnalysisPolicy.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ public abstract class AnalysisPolicy {
6464
protected final boolean relaxTypeFlowConstraints;
6565
protected final boolean removeSaturatedTypeFlows;
6666
protected final int typeFlowSaturationCutoff;
67+
protected final boolean allocationSiteSensitiveHeap;
68+
protected final int maxHeapContextDepth;
69+
protected final boolean limitObjectArrayLength;
70+
protected final int maxObjectSetSize;
6771

6872
public AnalysisPolicy(OptionValues options) {
6973
this.options = options;
@@ -72,6 +76,11 @@ public AnalysisPolicy(OptionValues options) {
7276
relaxTypeFlowConstraints = PointstoOptions.RelaxTypeFlowStateConstraints.getValue(options);
7377
removeSaturatedTypeFlows = PointstoOptions.RemoveSaturatedTypeFlows.getValue(options);
7478
typeFlowSaturationCutoff = PointstoOptions.TypeFlowSaturationCutoff.getValue(options);
79+
allocationSiteSensitiveHeap = PointstoOptions.AllocationSiteSensitiveHeap.getValue(options);
80+
maxHeapContextDepth = PointstoOptions.MaxHeapContextDepth.getValue(options);
81+
limitObjectArrayLength = PointstoOptions.LimitObjectArrayLength.getValue(options);
82+
maxObjectSetSize = PointstoOptions.MaxObjectSetSize.getValue(options);
83+
7584
}
7685

7786
public abstract boolean isContextSensitiveAnalysis();
@@ -92,6 +101,18 @@ public int typeFlowSaturationCutoff() {
92101
return typeFlowSaturationCutoff;
93102
}
94103

104+
public boolean allocationSiteSensitiveHeap() {
105+
return allocationSiteSensitiveHeap;
106+
}
107+
108+
public boolean limitObjectArrayLength() {
109+
return limitObjectArrayLength;
110+
}
111+
112+
public int maxObjectSetSize() {
113+
return maxObjectSetSize;
114+
}
115+
95116
public abstract MethodTypeFlow createMethodTypeFlow(PointsToAnalysisMethod method);
96117

97118
/**

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/ArrayCopyTypeFlow.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
package com.oracle.graal.pointsto.flow;
2626

2727
import com.oracle.graal.pointsto.PointsToAnalysis;
28-
import com.oracle.graal.pointsto.api.PointstoOptions;
2928
import com.oracle.graal.pointsto.flow.context.object.AnalysisObject;
3029
import com.oracle.graal.pointsto.meta.AnalysisType;
3130
import com.oracle.graal.pointsto.typestate.TypeState;
@@ -84,7 +83,7 @@ public void onObservedUpdate(PointsToAnalysis bb) {
8483
* applications. So we optimize it as much as possible: We compute the delta of added source
8584
* and destination types, to avoid re-processing the same elements over and over.
8685
*/
87-
if (lastSrc == null || lastDst == null || PointstoOptions.AllocationSiteSensitiveHeap.getValue(bb.getOptions())) {
86+
if (lastSrc == null || lastDst == null || bb.analysisPolicy().allocationSiteSensitiveHeap()) {
8887
/*
8988
* No previous state available, process the full type states. We also need to do that
9089
* when using the allocation site context, because TypeState.forSubtraction does not

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/context/bytecode/BytecodeSensitiveAnalysisPolicy.java

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
import com.oracle.graal.pointsto.AnalysisPolicy;
3636
import com.oracle.graal.pointsto.BigBang;
3737
import com.oracle.graal.pointsto.PointsToAnalysis;
38-
import com.oracle.graal.pointsto.api.PointstoOptions;
3938
import com.oracle.graal.pointsto.flow.AbstractSpecialInvokeTypeFlow;
4039
import com.oracle.graal.pointsto.flow.AbstractStaticInvokeTypeFlow;
4140
import com.oracle.graal.pointsto.flow.AbstractVirtualInvokeTypeFlow;
@@ -79,7 +78,7 @@
7978
import jdk.vm.ci.code.BytecodePosition;
8079
import jdk.vm.ci.meta.JavaConstant;
8180

82-
public class BytecodeSensitiveAnalysisPolicy extends AnalysisPolicy {
81+
public final class BytecodeSensitiveAnalysisPolicy extends AnalysisPolicy {
8382

8483
private final BytecodeAnalysisContextPolicy contextPolicy;
8584

@@ -143,7 +142,7 @@ public boolean isContextSensitiveAllocation(PointsToAnalysis bb, AnalysisType ty
143142

144143
@Override
145144
public AnalysisObject createHeapObject(PointsToAnalysis bb, AnalysisType type, BytecodePosition allocationSite, AnalysisContext allocationContext) {
146-
assert PointstoOptions.AllocationSiteSensitiveHeap.getValue(options);
145+
assert allocationSiteSensitiveHeap;
147146
if (isContextSensitiveAllocation(bb, type, allocationContext)) {
148147
return new AllocationContextSensitiveObject(bb, type, allocationSite, allocationContext);
149148
} else {
@@ -268,7 +267,7 @@ public void linkClonedObjects(PointsToAnalysis bb, TypeFlow<?> inputFlow, CloneT
268267

269268
@Override
270269
public FieldTypeStore createFieldTypeStore(PointsToAnalysis bb, AnalysisObject object, AnalysisField field, AnalysisUniverse universe) {
271-
assert PointstoOptions.AllocationSiteSensitiveHeap.getValue(options);
270+
assert allocationSiteSensitiveHeap;
272271
if (object.isContextInsensitiveObject()) {
273272
/*
274273
* Write flow is context-sensitive and read flow is context-insensitive. This split is
@@ -296,7 +295,7 @@ public FieldTypeStore createFieldTypeStore(PointsToAnalysis bb, AnalysisObject o
296295

297296
@Override
298297
public ArrayElementsTypeStore createArrayElementsTypeStore(AnalysisObject object, AnalysisUniverse universe) {
299-
assert PointstoOptions.AllocationSiteSensitiveHeap.getValue(options);
298+
assert allocationSiteSensitiveHeap;
300299
if (object.type().isArray()) {
301300
if (aliasArrayTypeFlows) {
302301
/* Alias all array type flows using the elements type flow model of Object type. */
@@ -345,7 +344,7 @@ public MethodFlowsGraphInfo staticRootMethodGraph(PointsToAnalysis bb, PointsToA
345344

346345
@Override
347346
public AnalysisContext allocationContext(PointsToAnalysis bb, MethodFlowsGraph callerGraph) {
348-
return contextPolicy.allocationContext((BytecodeAnalysisContext) ((MethodFlowsGraphClone) callerGraph).context(), PointstoOptions.MaxHeapContextDepth.getValue(bb.getOptions()));
347+
return contextPolicy.allocationContext((BytecodeAnalysisContext) ((MethodFlowsGraphClone) callerGraph).context(), maxHeapContextDepth);
349348
}
350349

351350
@Override
@@ -595,7 +594,7 @@ public TypeState doUnion(PointsToAnalysis bb, MultiTypeState state1, MultiTypeSt
595594
return doUnion0(bb, s1, s2, resultCanBeNull);
596595
}
597596

598-
private static TypeState doUnion0(PointsToAnalysis bb, ContextSensitiveMultiTypeState s1, ContextSensitiveMultiTypeState s2, boolean resultCanBeNull) {
597+
private TypeState doUnion0(PointsToAnalysis bb, ContextSensitiveMultiTypeState s1, ContextSensitiveMultiTypeState s2, boolean resultCanBeNull) {
599598

600599
/* Speculate that s1 and s2 are distinct sets. */
601600

@@ -631,8 +630,8 @@ private static TypeState doUnion0(PointsToAnalysis bb, ContextSensitiveMultiType
631630
return doUnion1(bb, s1, s2, resultCanBeNull);
632631
}
633632

634-
private static TypeState doUnion1(PointsToAnalysis bb, ContextSensitiveMultiTypeState s1, ContextSensitiveMultiTypeState s2, boolean resultCanBeNull) {
635-
if (PointstoOptions.AllocationSiteSensitiveHeap.getValue(bb.getOptions())) {
633+
private TypeState doUnion1(PointsToAnalysis bb, ContextSensitiveMultiTypeState s1, ContextSensitiveMultiTypeState s2, boolean resultCanBeNull) {
634+
if (allocationSiteSensitiveHeap) {
636635
return allocationSensitiveSpeculativeUnion1(bb, s1, s2, resultCanBeNull);
637636
} else {
638637
return allocationInsensitiveSpeculativeUnion1(bb, s1, s2, resultCanBeNull);
@@ -642,7 +641,7 @@ private static TypeState doUnion1(PointsToAnalysis bb, ContextSensitiveMultiType
642641
/**
643642
* Optimization that gives 1.5-3x in performance for the (typeflow) phase.
644643
*/
645-
private static TypeState allocationInsensitiveSpeculativeUnion1(PointsToAnalysis bb, ContextSensitiveMultiTypeState s1, ContextSensitiveMultiTypeState s2, boolean resultCanBeNull) {
644+
private TypeState allocationInsensitiveSpeculativeUnion1(PointsToAnalysis bb, ContextSensitiveMultiTypeState s1, ContextSensitiveMultiTypeState s2, boolean resultCanBeNull) {
646645
if (s1.bitSet().length() >= s2.bitSet().length()) {
647646
long[] bits1 = TypeStateUtils.extractBitSetField(s1.bitSet());
648647
long[] bits2 = TypeStateUtils.extractBitSetField(s2.bitSet());
@@ -664,7 +663,7 @@ private static TypeState allocationInsensitiveSpeculativeUnion1(PointsToAnalysis
664663
return doUnion2(bb, s1, s2, resultCanBeNull, 0, 0);
665664
}
666665

667-
private static TypeState allocationSensitiveSpeculativeUnion1(PointsToAnalysis bb, ContextSensitiveMultiTypeState s1, ContextSensitiveMultiTypeState s2, boolean resultCanBeNull) {
666+
private TypeState allocationSensitiveSpeculativeUnion1(PointsToAnalysis bb, ContextSensitiveMultiTypeState s1, ContextSensitiveMultiTypeState s2, boolean resultCanBeNull) {
668667
int idx1 = 0;
669668
int idx2 = 0;
670669
AnalysisPolicy analysisPolicy = bb.analysisPolicy();
@@ -701,7 +700,7 @@ private static TypeState allocationSensitiveSpeculativeUnion1(PointsToAnalysis b
701700
private static final ThreadLocal<UnsafeArrayListClosable<AnalysisObject>> doUnion2TL = new ThreadLocal<>();
702701
private static final ThreadLocal<UnsafeArrayListClosable<AnalysisObject>> doUnion2ObjectsTL = new ThreadLocal<>();
703702

704-
private static TypeState doUnion2(PointsToAnalysis bb, ContextSensitiveMultiTypeState s1, ContextSensitiveMultiTypeState s2, boolean resultCanBeNull, int startId1, int startId2) {
703+
private TypeState doUnion2(PointsToAnalysis bb, ContextSensitiveMultiTypeState s1, ContextSensitiveMultiTypeState s2, boolean resultCanBeNull, int startId1, int startId2) {
705704
try (UnsafeArrayListClosable<AnalysisObject> resultObjectsClosable = getTLArrayList(doUnion2TL, s1.objects.length + s2.objects.length)) {
706705
UnsafeArrayList<AnalysisObject> resultObjects = resultObjectsClosable.list();
707706
/* Add the beginning of the s1 list that we already walked above. */
@@ -757,7 +756,7 @@ private static TypeState doUnion2(PointsToAnalysis bb, ContextSensitiveMultiType
757756
* Check if the union of objects of a type in the overlapping section reached the
758757
* limit. The limit, bb.options().maxObjectSetSize(), has a minimum value of 1.
759758
*/
760-
if (PointstoOptions.LimitObjectArrayLength.getValue(bb.getOptions()) && unionObjects.size() > PointstoOptions.MaxObjectSetSize.getValue(bb.getOptions())) {
759+
if (limitObjectArrayLength && unionObjects.size() > maxObjectSetSize) {
761760
int idxStart = 0;
762761
int idxEnd = 0;
763762
while (idxEnd < unionObjects.size()) {
@@ -772,7 +771,7 @@ private static TypeState doUnion2(PointsToAnalysis bb, ContextSensitiveMultiType
772771
* stride
773772
*/
774773
int size = idxEnd - idxStart;
775-
if (size > PointstoOptions.MaxObjectSetSize.getValue(bb.getOptions())) {
774+
if (size > maxObjectSetSize) {
776775
/*
777776
* Object count exceeds the limit. Mark the objects in the stride as
778777
* merged.

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/context/object/AllocationContextSensitiveObject.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
package com.oracle.graal.pointsto.flow.context.object;
2626

2727
import com.oracle.graal.pointsto.PointsToAnalysis;
28-
import com.oracle.graal.pointsto.api.PointstoOptions;
2928
import com.oracle.graal.pointsto.flow.ArrayElementsTypeFlow;
3029
import com.oracle.graal.pointsto.flow.context.AnalysisContext;
3130
import com.oracle.graal.pointsto.meta.AnalysisType;
@@ -73,7 +72,7 @@ public void setAllocatorContext(AnalysisContext allocatorContext) {
7372
@Override
7473
public ArrayElementsTypeFlow getArrayElementsFlow(PointsToAnalysis bb, boolean isStore) {
7574
assert type.isArray();
76-
assert PointstoOptions.AllocationSiteSensitiveHeap.getValue(bb.getOptions());
75+
assert bb.analysisPolicy().allocationSiteSensitiveHeap();
7776

7877
if (!arrayElementsTypeStore.writeFlow().getState().canBeNull()) {
7978
/*

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/context/object/ContextSensitiveAnalysisObject.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
import java.util.List;
3030

3131
import com.oracle.graal.pointsto.PointsToAnalysis;
32-
import com.oracle.graal.pointsto.api.PointstoOptions;
3332
import com.oracle.graal.pointsto.flow.ArrayElementsTypeFlow;
3433
import com.oracle.graal.pointsto.flow.FieldFilterTypeFlow;
3534
import com.oracle.graal.pointsto.flow.FieldTypeFlow;
@@ -52,7 +51,7 @@ public class ContextSensitiveAnalysisObject extends AnalysisObject {
5251

5352
public ContextSensitiveAnalysisObject(AnalysisUniverse universe, AnalysisType type, AnalysisObjectKind kind) {
5453
super(universe, type, kind);
55-
assert PointstoOptions.AllocationSiteSensitiveHeap.getValue(universe.hostVM().options());
54+
assert universe.analysisPolicy().allocationSiteSensitiveHeap();
5655
}
5756

5857
/** The object has been in contact with an context insensitive object in an union operation. */
@@ -121,15 +120,15 @@ protected static void mergeInstanceFieldFlow(PointsToAnalysis bb, FieldTypeStore
121120
@Override
122121
public ArrayElementsTypeFlow getArrayElementsFlow(PointsToAnalysis bb, boolean isStore) {
123122
assert type.isArray();
124-
assert PointstoOptions.AllocationSiteSensitiveHeap.getValue(bb.getOptions());
123+
assert bb.analysisPolicy().allocationSiteSensitiveHeap();
125124

126125
return isStore ? arrayElementsTypeStore.writeFlow() : arrayElementsTypeStore.readFlow();
127126
}
128127

129128
/** Returns the filter field flow corresponding to an unsafe accessed field. */
130129
@Override
131130
public FieldFilterTypeFlow getInstanceFieldFilterFlow(PointsToAnalysis bb, TypeFlow<?> objectFlow, BytecodePosition context, AnalysisField field) {
132-
assert !Modifier.isStatic(field.getModifiers()) && field.isUnsafeAccessed() && PointstoOptions.AllocationSiteSensitiveHeap.getValue(bb.getOptions());
131+
assert !Modifier.isStatic(field.getModifiers()) && field.isUnsafeAccessed() && bb.analysisPolicy().allocationSiteSensitiveHeap();
133132

134133
FieldTypeStore fieldTypeStore = getInstanceFieldTypeStore(bb, objectFlow, context, field);
135134

@@ -146,7 +145,7 @@ public FieldFilterTypeFlow getInstanceFieldFilterFlow(PointsToAnalysis bb, TypeF
146145

147146
@Override
148147
public FieldTypeFlow getInstanceFieldFlow(PointsToAnalysis bb, TypeFlow<?> objectFlow, BytecodePosition context, AnalysisField field, boolean isStore) {
149-
assert !Modifier.isStatic(field.getModifiers()) && PointstoOptions.AllocationSiteSensitiveHeap.getValue(bb.getOptions());
148+
assert !Modifier.isStatic(field.getModifiers()) && bb.analysisPolicy().allocationSiteSensitiveHeap();
150149

151150
FieldTypeStore fieldTypeStore = getInstanceFieldTypeStore(bb, objectFlow, context, field);
152151

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/typestate/TypeStateUtils.java

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434

3535
import com.oracle.graal.pointsto.BigBang;
3636
import com.oracle.graal.pointsto.PointsToAnalysis;
37-
import com.oracle.graal.pointsto.api.PointstoOptions;
3837
import com.oracle.graal.pointsto.flow.context.object.AnalysisObject;
3938
import com.oracle.graal.pointsto.meta.AnalysisType;
4039
import com.oracle.svm.util.ReflectionUtil;
@@ -45,10 +44,12 @@
4544
public class TypeStateUtils {
4645

4746
private static final MethodHandle bitSetArrayAccess;
47+
private static final MethodHandle wordInUseAccess;
4848
private static final MethodHandle trimToSizeAccess;
4949
static {
5050
try {
5151
bitSetArrayAccess = MethodHandles.lookup().unreflectGetter(ReflectionUtil.lookupField(BitSet.class, "words"));
52+
wordInUseAccess = MethodHandles.lookup().unreflectGetter(ReflectionUtil.lookupField(BitSet.class, "wordsInUse"));
5253
trimToSizeAccess = MethodHandles.lookup().unreflect(ReflectionUtil.lookupMethod(BitSet.class, "trimToSize"));
5354
} catch (IllegalAccessException t) {
5455
throw JVMCIError.shouldNotReachHere(t);
@@ -72,6 +73,28 @@ public static long[] extractBitSetField(BitSet bitSet) {
7273
}
7374
}
7475

76+
public static int extractWordsInUseField(BitSet bitSet) {
77+
try {
78+
return (int) wordInUseAccess.invokeExact(bitSet);
79+
} catch (Throwable t) {
80+
throw JVMCIError.shouldNotReachHere(t);
81+
}
82+
}
83+
84+
public static boolean needsTrim(BitSet bitSet) {
85+
int wordsInUse = extractWordsInUseField(bitSet);
86+
long[] words = extractBitSetField(bitSet);
87+
return wordsInUse != words.length;
88+
}
89+
90+
public static void trimBitSetToSize(BitSet bs) {
91+
try {
92+
trimToSizeAccess.invokeExact(bs);
93+
} catch (Throwable t) {
94+
throw JVMCIError.shouldNotReachHere(t);
95+
}
96+
}
97+
7598
/** Return true if {@code first} is a superset of {@code second}. */
7699
public static boolean isSuperset(BitSet first, BitSet second) {
77100
if (first.length() >= second.length()) {
@@ -92,15 +115,6 @@ public static boolean isSuperset(BitSet first, BitSet second) {
92115
return false;
93116
}
94117

95-
public static void trimBitSetToSize(BitSet bs) {
96-
try {
97-
trimToSizeAccess.invokeExact(bs);
98-
} catch (Throwable t) {
99-
throw JVMCIError.shouldNotReachHere(t);
100-
}
101-
102-
}
103-
104118
public static AnalysisObject[] concat(AnalysisObject[] oa1, AnalysisObject[] oa2) {
105119
int resultSize = oa1.length + oa2.length;
106120

@@ -226,7 +240,7 @@ private static AnalysisObject[] arraysUnion(PointsToAnalysis bb, AnalysisObject[
226240
private static AnalysisObject[] checkUnionSize(PointsToAnalysis bb, AnalysisObject[] oa1, AnalysisObject[] oa2, AnalysisObject[] result) {
227241
assert result.length >= 2;
228242

229-
if (PointstoOptions.LimitObjectArrayLength.getValue(bb.getOptions()) && (result.length > PointstoOptions.MaxObjectSetSize.getValue(bb.getOptions()))) {
243+
if (bb.analysisPolicy().limitObjectArrayLength() && (result.length > bb.analysisPolicy().maxObjectSetSize())) {
230244
AnalysisObject rObj = result[0].type().getContextInsensitiveAnalysisObject();
231245
bb.analysisPolicy().noteMerge(bb, oa1);
232246
bb.analysisPolicy().noteMerge(bb, oa2);
@@ -324,7 +338,7 @@ private static AnalysisObject[] arraysIntersection(PointsToAnalysis bb, Analysis
324338
* If the LimitObjectArrayLength is enabled then the result MUST be smaller than
325339
* MaxObjectSetSize.
326340
*/
327-
assert !PointstoOptions.LimitObjectArrayLength.getValue(bb.getOptions()) || rList.size() <= PointstoOptions.MaxObjectSetSize.getValue(bb.getOptions());
341+
assert !bb.analysisPolicy().limitObjectArrayLength() || rList.size() <= bb.analysisPolicy().maxObjectSetSize();
328342

329343
if (rList.size() == 0) {
330344
return AnalysisObject.EMPTY_ARRAY;
@@ -422,7 +436,7 @@ public static BitSet set(BitSet bs1, int bitIndex) {
422436
/* Check if the new bit index exceeds the capacity of bs1. */
423437
if (bitIndex > highestSetIndex) {
424438
/* Preallocate the bit set to represent bitIndex without expansion. */
425-
bsr = new BitSet(bitIndex);
439+
bsr = new BitSet(bitIndex + 1);
426440
/* First add in the original bits, which will System.arraycopy() bs1 bits into bsr. */
427441
bsr.or(bs1);
428442
/* ... then set the new index. */
@@ -433,16 +447,18 @@ public static BitSet set(BitSet bs1, int bitIndex) {
433447
bsr = (BitSet) bs1.clone();
434448
bsr.set(bitIndex);
435449
}
450+
assert !needsTrim(bsr);
436451
return bsr;
437452
}
438453

439454
/** Create a new bit set with the bits of the inputs IDs set. */
440455
public static BitSet newBitSet(int index1, int index2) {
441456
/* Preallocate the result bit set to represent index1 and index2 without any expansion. */
442-
BitSet typesBitSet = new BitSet(Math.max(index1, index2));
443-
typesBitSet.set(index1);
444-
typesBitSet.set(index2);
445-
return typesBitSet;
457+
BitSet bs = new BitSet(Math.max(index1, index2) + 1);
458+
bs.set(index1);
459+
bs.set(index2);
460+
assert !needsTrim(bs);
461+
return bs;
446462
}
447463

448464
public static boolean closeToAllInstantiated(BigBang bb, TypeState state) {

0 commit comments

Comments
 (0)