Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ public abstract class AnalysisPolicy {
protected final boolean relaxTypeFlowConstraints;
protected final boolean removeSaturatedTypeFlows;
protected final int typeFlowSaturationCutoff;
protected final boolean allocationSiteSensitiveHeap;
protected final int maxHeapContextDepth;
protected final boolean limitObjectArrayLength;
protected final int maxObjectSetSize;

public AnalysisPolicy(OptionValues options) {
this.options = options;
Expand All @@ -72,6 +76,11 @@ public AnalysisPolicy(OptionValues options) {
relaxTypeFlowConstraints = PointstoOptions.RelaxTypeFlowStateConstraints.getValue(options);
removeSaturatedTypeFlows = PointstoOptions.RemoveSaturatedTypeFlows.getValue(options);
typeFlowSaturationCutoff = PointstoOptions.TypeFlowSaturationCutoff.getValue(options);
allocationSiteSensitiveHeap = PointstoOptions.AllocationSiteSensitiveHeap.getValue(options);
maxHeapContextDepth = PointstoOptions.MaxHeapContextDepth.getValue(options);
limitObjectArrayLength = PointstoOptions.LimitObjectArrayLength.getValue(options);
maxObjectSetSize = PointstoOptions.MaxObjectSetSize.getValue(options);

}

public abstract boolean isContextSensitiveAnalysis();
Expand All @@ -92,6 +101,18 @@ public int typeFlowSaturationCutoff() {
return typeFlowSaturationCutoff;
}

public boolean allocationSiteSensitiveHeap() {
return allocationSiteSensitiveHeap;
}

public boolean limitObjectArrayLength() {
return limitObjectArrayLength;
}

public int maxObjectSetSize() {
return maxObjectSetSize;
}

public abstract MethodTypeFlow createMethodTypeFlow(PointsToAnalysisMethod method);

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
package com.oracle.graal.pointsto.flow;

import com.oracle.graal.pointsto.PointsToAnalysis;
import com.oracle.graal.pointsto.api.PointstoOptions;
import com.oracle.graal.pointsto.flow.context.object.AnalysisObject;
import com.oracle.graal.pointsto.meta.AnalysisType;
import com.oracle.graal.pointsto.typestate.TypeState;
Expand Down Expand Up @@ -84,7 +83,7 @@ public void onObservedUpdate(PointsToAnalysis bb) {
* applications. So we optimize it as much as possible: We compute the delta of added source
* and destination types, to avoid re-processing the same elements over and over.
*/
if (lastSrc == null || lastDst == null || PointstoOptions.AllocationSiteSensitiveHeap.getValue(bb.getOptions())) {
if (lastSrc == null || lastDst == null || bb.analysisPolicy().allocationSiteSensitiveHeap()) {
/*
* No previous state available, process the full type states. We also need to do that
* when using the allocation site context, because TypeState.forSubtraction does not
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
import com.oracle.graal.pointsto.AnalysisPolicy;
import com.oracle.graal.pointsto.BigBang;
import com.oracle.graal.pointsto.PointsToAnalysis;
import com.oracle.graal.pointsto.api.PointstoOptions;
import com.oracle.graal.pointsto.flow.AbstractSpecialInvokeTypeFlow;
import com.oracle.graal.pointsto.flow.AbstractStaticInvokeTypeFlow;
import com.oracle.graal.pointsto.flow.AbstractVirtualInvokeTypeFlow;
Expand Down Expand Up @@ -79,7 +78,7 @@
import jdk.vm.ci.code.BytecodePosition;
import jdk.vm.ci.meta.JavaConstant;

public class BytecodeSensitiveAnalysisPolicy extends AnalysisPolicy {
public final class BytecodeSensitiveAnalysisPolicy extends AnalysisPolicy {

private final BytecodeAnalysisContextPolicy contextPolicy;

Expand Down Expand Up @@ -143,7 +142,7 @@ public boolean isContextSensitiveAllocation(PointsToAnalysis bb, AnalysisType ty

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

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

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

@Override
public AnalysisContext allocationContext(PointsToAnalysis bb, MethodFlowsGraph callerGraph) {
return contextPolicy.allocationContext((BytecodeAnalysisContext) ((MethodFlowsGraphClone) callerGraph).context(), PointstoOptions.MaxHeapContextDepth.getValue(bb.getOptions()));
return contextPolicy.allocationContext((BytecodeAnalysisContext) ((MethodFlowsGraphClone) callerGraph).context(), maxHeapContextDepth);
}

@Override
Expand Down Expand Up @@ -595,7 +594,7 @@ public TypeState doUnion(PointsToAnalysis bb, MultiTypeState state1, MultiTypeSt
return doUnion0(bb, s1, s2, resultCanBeNull);
}

private static TypeState doUnion0(PointsToAnalysis bb, ContextSensitiveMultiTypeState s1, ContextSensitiveMultiTypeState s2, boolean resultCanBeNull) {
private TypeState doUnion0(PointsToAnalysis bb, ContextSensitiveMultiTypeState s1, ContextSensitiveMultiTypeState s2, boolean resultCanBeNull) {

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

Expand Down Expand Up @@ -631,8 +630,8 @@ private static TypeState doUnion0(PointsToAnalysis bb, ContextSensitiveMultiType
return doUnion1(bb, s1, s2, resultCanBeNull);
}

private static TypeState doUnion1(PointsToAnalysis bb, ContextSensitiveMultiTypeState s1, ContextSensitiveMultiTypeState s2, boolean resultCanBeNull) {
if (PointstoOptions.AllocationSiteSensitiveHeap.getValue(bb.getOptions())) {
private TypeState doUnion1(PointsToAnalysis bb, ContextSensitiveMultiTypeState s1, ContextSensitiveMultiTypeState s2, boolean resultCanBeNull) {
if (allocationSiteSensitiveHeap) {
return allocationSensitiveSpeculativeUnion1(bb, s1, s2, resultCanBeNull);
} else {
return allocationInsensitiveSpeculativeUnion1(bb, s1, s2, resultCanBeNull);
Expand All @@ -642,7 +641,7 @@ private static TypeState doUnion1(PointsToAnalysis bb, ContextSensitiveMultiType
/**
* Optimization that gives 1.5-3x in performance for the (typeflow) phase.
*/
private static TypeState allocationInsensitiveSpeculativeUnion1(PointsToAnalysis bb, ContextSensitiveMultiTypeState s1, ContextSensitiveMultiTypeState s2, boolean resultCanBeNull) {
private TypeState allocationInsensitiveSpeculativeUnion1(PointsToAnalysis bb, ContextSensitiveMultiTypeState s1, ContextSensitiveMultiTypeState s2, boolean resultCanBeNull) {
if (s1.bitSet().length() >= s2.bitSet().length()) {
long[] bits1 = TypeStateUtils.extractBitSetField(s1.bitSet());
long[] bits2 = TypeStateUtils.extractBitSetField(s2.bitSet());
Expand All @@ -664,7 +663,7 @@ private static TypeState allocationInsensitiveSpeculativeUnion1(PointsToAnalysis
return doUnion2(bb, s1, s2, resultCanBeNull, 0, 0);
}

private static TypeState allocationSensitiveSpeculativeUnion1(PointsToAnalysis bb, ContextSensitiveMultiTypeState s1, ContextSensitiveMultiTypeState s2, boolean resultCanBeNull) {
private TypeState allocationSensitiveSpeculativeUnion1(PointsToAnalysis bb, ContextSensitiveMultiTypeState s1, ContextSensitiveMultiTypeState s2, boolean resultCanBeNull) {
int idx1 = 0;
int idx2 = 0;
AnalysisPolicy analysisPolicy = bb.analysisPolicy();
Expand Down Expand Up @@ -701,7 +700,7 @@ private static TypeState allocationSensitiveSpeculativeUnion1(PointsToAnalysis b
private static final ThreadLocal<UnsafeArrayListClosable<AnalysisObject>> doUnion2TL = new ThreadLocal<>();
private static final ThreadLocal<UnsafeArrayListClosable<AnalysisObject>> doUnion2ObjectsTL = new ThreadLocal<>();

private static TypeState doUnion2(PointsToAnalysis bb, ContextSensitiveMultiTypeState s1, ContextSensitiveMultiTypeState s2, boolean resultCanBeNull, int startId1, int startId2) {
private TypeState doUnion2(PointsToAnalysis bb, ContextSensitiveMultiTypeState s1, ContextSensitiveMultiTypeState s2, boolean resultCanBeNull, int startId1, int startId2) {
try (UnsafeArrayListClosable<AnalysisObject> resultObjectsClosable = getTLArrayList(doUnion2TL, s1.objects.length + s2.objects.length)) {
UnsafeArrayList<AnalysisObject> resultObjects = resultObjectsClosable.list();
/* Add the beginning of the s1 list that we already walked above. */
Expand Down Expand Up @@ -757,7 +756,7 @@ private static TypeState doUnion2(PointsToAnalysis bb, ContextSensitiveMultiType
* Check if the union of objects of a type in the overlapping section reached the
* limit. The limit, bb.options().maxObjectSetSize(), has a minimum value of 1.
*/
if (PointstoOptions.LimitObjectArrayLength.getValue(bb.getOptions()) && unionObjects.size() > PointstoOptions.MaxObjectSetSize.getValue(bb.getOptions())) {
if (limitObjectArrayLength && unionObjects.size() > maxObjectSetSize) {
int idxStart = 0;
int idxEnd = 0;
while (idxEnd < unionObjects.size()) {
Expand All @@ -772,7 +771,7 @@ private static TypeState doUnion2(PointsToAnalysis bb, ContextSensitiveMultiType
* stride
*/
int size = idxEnd - idxStart;
if (size > PointstoOptions.MaxObjectSetSize.getValue(bb.getOptions())) {
if (size > maxObjectSetSize) {
/*
* Object count exceeds the limit. Mark the objects in the stride as
* merged.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
package com.oracle.graal.pointsto.flow.context.object;

import com.oracle.graal.pointsto.PointsToAnalysis;
import com.oracle.graal.pointsto.api.PointstoOptions;
import com.oracle.graal.pointsto.flow.ArrayElementsTypeFlow;
import com.oracle.graal.pointsto.flow.context.AnalysisContext;
import com.oracle.graal.pointsto.meta.AnalysisType;
Expand Down Expand Up @@ -73,7 +72,7 @@ public void setAllocatorContext(AnalysisContext allocatorContext) {
@Override
public ArrayElementsTypeFlow getArrayElementsFlow(PointsToAnalysis bb, boolean isStore) {
assert type.isArray();
assert PointstoOptions.AllocationSiteSensitiveHeap.getValue(bb.getOptions());
assert bb.analysisPolicy().allocationSiteSensitiveHeap();

if (!arrayElementsTypeStore.writeFlow().getState().canBeNull()) {
/*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
import java.util.List;

import com.oracle.graal.pointsto.PointsToAnalysis;
import com.oracle.graal.pointsto.api.PointstoOptions;
import com.oracle.graal.pointsto.flow.ArrayElementsTypeFlow;
import com.oracle.graal.pointsto.flow.FieldFilterTypeFlow;
import com.oracle.graal.pointsto.flow.FieldTypeFlow;
Expand All @@ -52,7 +51,7 @@ public class ContextSensitiveAnalysisObject extends AnalysisObject {

public ContextSensitiveAnalysisObject(AnalysisUniverse universe, AnalysisType type, AnalysisObjectKind kind) {
super(universe, type, kind);
assert PointstoOptions.AllocationSiteSensitiveHeap.getValue(universe.hostVM().options());
assert universe.analysisPolicy().allocationSiteSensitiveHeap();
}

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

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

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

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

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

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

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@

import com.oracle.graal.pointsto.BigBang;
import com.oracle.graal.pointsto.PointsToAnalysis;
import com.oracle.graal.pointsto.api.PointstoOptions;
import com.oracle.graal.pointsto.flow.context.object.AnalysisObject;
import com.oracle.graal.pointsto.meta.AnalysisType;
import com.oracle.svm.util.ReflectionUtil;
Expand All @@ -45,10 +44,12 @@
public class TypeStateUtils {

private static final MethodHandle bitSetArrayAccess;
private static final MethodHandle wordInUseAccess;
private static final MethodHandle trimToSizeAccess;
static {
try {
bitSetArrayAccess = MethodHandles.lookup().unreflectGetter(ReflectionUtil.lookupField(BitSet.class, "words"));
wordInUseAccess = MethodHandles.lookup().unreflectGetter(ReflectionUtil.lookupField(BitSet.class, "wordsInUse"));
trimToSizeAccess = MethodHandles.lookup().unreflect(ReflectionUtil.lookupMethod(BitSet.class, "trimToSize"));
} catch (IllegalAccessException t) {
throw JVMCIError.shouldNotReachHere(t);
Expand All @@ -72,6 +73,28 @@ public static long[] extractBitSetField(BitSet bitSet) {
}
}

public static int extractWordsInUseField(BitSet bitSet) {
try {
return (int) wordInUseAccess.invokeExact(bitSet);
} catch (Throwable t) {
throw JVMCIError.shouldNotReachHere(t);
}
}

public static boolean needsTrim(BitSet bitSet) {
int wordsInUse = extractWordsInUseField(bitSet);
long[] words = extractBitSetField(bitSet);
return wordsInUse != words.length;
}

public static void trimBitSetToSize(BitSet bs) {
try {
trimToSizeAccess.invokeExact(bs);
} catch (Throwable t) {
throw JVMCIError.shouldNotReachHere(t);
}
}

/** Return true if {@code first} is a superset of {@code second}. */
public static boolean isSuperset(BitSet first, BitSet second) {
if (first.length() >= second.length()) {
Expand All @@ -92,15 +115,6 @@ public static boolean isSuperset(BitSet first, BitSet second) {
return false;
}

public static void trimBitSetToSize(BitSet bs) {
try {
trimToSizeAccess.invokeExact(bs);
} catch (Throwable t) {
throw JVMCIError.shouldNotReachHere(t);
}

}

public static AnalysisObject[] concat(AnalysisObject[] oa1, AnalysisObject[] oa2) {
int resultSize = oa1.length + oa2.length;

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

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

if (rList.size() == 0) {
return AnalysisObject.EMPTY_ARRAY;
Expand Down Expand Up @@ -422,7 +436,7 @@ public static BitSet set(BitSet bs1, int bitIndex) {
/* Check if the new bit index exceeds the capacity of bs1. */
if (bitIndex > highestSetIndex) {
/* Preallocate the bit set to represent bitIndex without expansion. */
bsr = new BitSet(bitIndex);
bsr = new BitSet(bitIndex + 1);
/* First add in the original bits, which will System.arraycopy() bs1 bits into bsr. */
bsr.or(bs1);
/* ... then set the new index. */
Expand All @@ -433,16 +447,18 @@ public static BitSet set(BitSet bs1, int bitIndex) {
bsr = (BitSet) bs1.clone();
bsr.set(bitIndex);
}
assert !needsTrim(bsr);
return bsr;
}

/** Create a new bit set with the bits of the inputs IDs set. */
public static BitSet newBitSet(int index1, int index2) {
/* Preallocate the result bit set to represent index1 and index2 without any expansion. */
BitSet typesBitSet = new BitSet(Math.max(index1, index2));
typesBitSet.set(index1);
typesBitSet.set(index2);
return typesBitSet;
BitSet bs = new BitSet(Math.max(index1, index2) + 1);
bs.set(index1);
bs.set(index2);
assert !needsTrim(bs);
return bs;
}

public static boolean closeToAllInstantiated(BigBang bb, TypeState state) {
Expand Down
Loading