Skip to content

Commit 4ad2a38

Browse files
committed
Extract inner classes.
1 parent 7736690 commit 4ad2a38

9 files changed

+846
-563
lines changed

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

Lines changed: 1 addition & 304 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,10 @@
2525
package com.oracle.graal.pointsto.flow.context.bytecode;
2626

2727
import static com.oracle.graal.pointsto.util.ListUtils.getTLArrayList;
28-
import static jdk.vm.ci.common.JVMCIError.guarantee;
2928

3029
import java.lang.reflect.Modifier;
31-
import java.util.ArrayList;
3230
import java.util.Arrays;
3331
import java.util.BitSet;
34-
import java.util.Collection;
35-
import java.util.Collections;
36-
import java.util.concurrent.ConcurrentHashMap;
37-
import java.util.concurrent.ConcurrentMap;
3832

3933
import org.graalvm.compiler.options.OptionValues;
4034

@@ -50,7 +44,6 @@
5044
import com.oracle.graal.pointsto.flow.CallSiteSensitiveMethodTypeFlow;
5145
import com.oracle.graal.pointsto.flow.CloneTypeFlow;
5246
import com.oracle.graal.pointsto.flow.ContextInsensitiveFieldTypeFlow;
53-
import com.oracle.graal.pointsto.flow.DirectInvokeTypeFlow;
5447
import com.oracle.graal.pointsto.flow.FieldTypeFlow;
5548
import com.oracle.graal.pointsto.flow.InvokeTypeFlow;
5649
import com.oracle.graal.pointsto.flow.MethodFlowsGraph;
@@ -78,7 +71,6 @@
7871
import com.oracle.graal.pointsto.typestore.SplitFieldTypeStore;
7972
import com.oracle.graal.pointsto.typestore.UnifiedArrayElementsTypeStore;
8073
import com.oracle.graal.pointsto.typestore.UnifiedFieldTypeStore;
81-
import com.oracle.graal.pointsto.util.AnalysisError;
8274
import com.oracle.graal.pointsto.util.ListUtils;
8375
import com.oracle.graal.pointsto.util.ListUtils.UnsafeArrayList;
8476
import com.oracle.graal.pointsto.util.ListUtils.UnsafeArrayListClosable;
@@ -385,305 +377,10 @@ public void registerAsImplementationInvoked(InvokeTypeFlow invoke, MethodFlowsGr
385377
}
386378
}
387379

388-
private static BytecodeAnalysisContextPolicy contextPolicy(BigBang bb) {
380+
static BytecodeAnalysisContextPolicy contextPolicy(BigBang bb) {
389381
return ((BytecodeSensitiveAnalysisPolicy) bb.analysisPolicy()).getContextPolicy();
390382
}
391383

392-
/**
393-
* Bytecode context sensitive implementation of the invoke virtual type flow update.
394-
*
395-
* TODO Can we merge the slow path (i.e., this class) and fast path (i.e., the default, context
396-
* insensitive virtual invoke implementation) to be able to fall back to fast path when context
397-
* sensitivity is disabled or reaches budget threshold?
398-
*/
399-
private static class BytecodeSensitiveVirtualInvokeTypeFlow extends AbstractVirtualInvokeTypeFlow {
400-
401-
/*
402-
* Remember all the callee clones that were already linked in each context at this
403-
* invocation site to avoid redundant relinking. MethodFlows is unique for each method type
404-
* flow and context combination.
405-
*/
406-
private final ConcurrentMap<MethodFlowsGraph, Object> calleesFlows = new ConcurrentHashMap<>(4, 0.75f, 1);
407-
private final AnalysisContext callerContext;
408-
409-
protected BytecodeSensitiveVirtualInvokeTypeFlow(BytecodePosition invokeLocation, AnalysisType receiverType, PointsToAnalysisMethod targetMethod,
410-
TypeFlow<?>[] actualParameters, ActualReturnTypeFlow actualReturn, BytecodeLocation location) {
411-
super(invokeLocation, receiverType, targetMethod, actualParameters, actualReturn, location);
412-
callerContext = null;
413-
}
414-
415-
protected BytecodeSensitiveVirtualInvokeTypeFlow(PointsToAnalysis bb, MethodFlowsGraph methodFlows, BytecodeSensitiveVirtualInvokeTypeFlow original) {
416-
super(bb, methodFlows, original);
417-
callerContext = ((MethodFlowsGraphClone) methodFlows).context();
418-
}
419-
420-
@Override
421-
public TypeFlow<BytecodePosition> copy(PointsToAnalysis bb, MethodFlowsGraph methodFlows) {
422-
return new BytecodeSensitiveVirtualInvokeTypeFlow(bb, methodFlows, this);
423-
}
424-
425-
@Override
426-
public void onObservedUpdate(PointsToAnalysis bb) {
427-
assert this.isClone() || this.isContextInsensitive();
428-
429-
/*
430-
* Capture the current receiver state before the update. The type state objects are
431-
* immutable and a later call to getState() can yield a different value.
432-
*/
433-
TypeState receiverState = getReceiver().getState();
434-
receiverState = filterReceiverState(bb, receiverState);
435-
436-
if (receiverState.isEmpty() || receiverState.isNull()) {
437-
return;
438-
}
439-
440-
/* Use the tandem types - objects iterator. */
441-
TypesObjectsIterator toi = new TypesObjectsIterator(receiverState);
442-
while (toi.hasNextType()) {
443-
AnalysisType type = toi.nextType();
444-
445-
AnalysisMethod method = type.resolveConcreteMethod(getTargetMethod());
446-
if (method == null || Modifier.isAbstract(method.getModifiers())) {
447-
/*
448-
* Type states can be conservative, i.e., we can have receiver types that do not
449-
* implement the method. Just ignore such types.
450-
*/
451-
while (toi.hasNextObject(type)) {
452-
// skip the rest of the objects of the same type
453-
toi.nextObject(type);
454-
}
455-
continue;
456-
}
457-
458-
assert !Modifier.isAbstract(method.getModifiers());
459-
460-
CallSiteSensitiveMethodTypeFlow callee = (CallSiteSensitiveMethodTypeFlow) PointsToAnalysis.assertPointsToAnalysisMethod(method).getTypeFlow();
461-
462-
while (toi.hasNextObject(type)) {
463-
AnalysisObject actualReceiverObject = toi.nextObject(type);
464-
465-
// get the context based on the actualReceiverObject
466-
AnalysisContext calleeContext = contextPolicy(bb).calleeContext(bb, actualReceiverObject, (BytecodeAnalysisContext) callerContext, callee);
467-
468-
MethodFlowsGraph calleeFlows = callee.addContext(bb, calleeContext, this);
469-
470-
if (calleesFlows.put(calleeFlows, Boolean.TRUE) == null) {
471-
/* register the analysis method as a callee for this invoke */
472-
addCallee(calleeFlows.getMethod());
473-
/* linkCallee() does not link the receiver object. */
474-
linkCallee(bb, false, calleeFlows);
475-
}
476-
477-
updateReceiver(bb, calleeFlows, actualReceiverObject);
478-
}
479-
480-
}
481-
}
482-
483-
@Override
484-
public void onObservedSaturated(PointsToAnalysis bb, TypeFlow<?> observed) {
485-
/* When the receiver flow saturates start observing the flow of the receiver type. */
486-
replaceObservedWith(bb, receiverType);
487-
}
488-
489-
@Override
490-
public Collection<MethodFlowsGraph> getCalleesFlows(PointsToAnalysis bb) {
491-
return new ArrayList<>(calleesFlows.keySet());
492-
}
493-
}
494-
495-
/**
496-
* This is a special iterator for the type state. It iterates over analysis types and objects in
497-
* tandem doing a single pass over the objects array. It relies on the fact that the types and
498-
* objects are sorted by ID. It is meant for situations where the types need some pre-processing
499-
* or checking before processing their respective objects, e.g., as in virtual method resolution
500-
* for InvokeTypeFlow. It those situations it avoids iterating over the types first and then
501-
* searching for the range of objects corresponding to that type. When only objects, or only
502-
* types, or only objects of a certain type need to be iterated use the other provided
503-
* iterators. A correct use of this iterator is as follows:
504-
*
505-
* <code>
506-
* TypesObjectsIterator toi = state.getTypesObjectsIterator();
507-
*
508-
* while(toi.hasNextType()) {
509-
* AnalysisType t = toi.nextType();
510-
* // use type here
511-
*
512-
* while(toi.hasNextObject(t)) {
513-
* AnalysisObject o = toi.nextObject(t);
514-
* // use object here
515-
* }
516-
* }
517-
* </code>
518-
*/
519-
public static class TypesObjectsIterator {
520-
private final int typesCount;
521-
private final AnalysisObject[] objects;
522-
private int typeIdx = 0;
523-
private int objectIdx = 0;
524-
525-
public TypesObjectsIterator(TypeState state) {
526-
typesCount = state.typesCount();
527-
objects = objectsArray(state);
528-
}
529-
530-
private static AnalysisObject[] objectsArray(TypeState state) {
531-
if (state.isEmpty() || state.isNull()) {
532-
return AnalysisObject.EMPTY_ARRAY;
533-
}
534-
if (state instanceof ContextSensitiveSingleTypeState) {
535-
return ((ContextSensitiveSingleTypeState) state).objects;
536-
}
537-
if (state instanceof ContextSensitiveMultiTypeState) {
538-
return ((ContextSensitiveMultiTypeState) state).objects;
539-
}
540-
throw AnalysisError.shouldNotReachHere();
541-
}
542-
543-
/**
544-
* Returns true if there is a next type in the objects array, i.e., there are objects of a
545-
* type other than the current type.
546-
*/
547-
public boolean hasNextType() {
548-
return typeIdx < typesCount;
549-
}
550-
551-
/** Returns true if there are more objects of the current type. */
552-
public boolean hasNextObject(AnalysisType type) {
553-
return objectIdx < objects.length && objects[objectIdx].getTypeId() == type.getId();
554-
}
555-
556-
/** Gets the next type. */
557-
public AnalysisType nextType() {
558-
/* Check that there is a next type. */
559-
assert hasNextType();
560-
/* Increment the type index. */
561-
typeIdx++;
562-
/* Return the type at the 'objectIdx. */
563-
return objects[objectIdx].type();
564-
}
565-
566-
/** Gets the next object. */
567-
public AnalysisObject nextObject(AnalysisType type) {
568-
/* Check that there is a next object of the desired type. */
569-
assert hasNextObject(type);
570-
/* Return the next object and increment objectIdx. */
571-
return objects[objectIdx++];
572-
}
573-
}
574-
575-
private static final class BytecodeSensitiveStaticInvokeTypeFlow extends AbstractStaticInvokeTypeFlow {
576-
577-
private AnalysisContext calleeContext;
578-
/**
579-
* Context of the caller.
580-
*/
581-
private AnalysisContext callerContext;
582-
583-
private BytecodeSensitiveStaticInvokeTypeFlow(BytecodePosition invokeLocation, AnalysisType receiverType, PointsToAnalysisMethod targetMethod,
584-
TypeFlow<?>[] actualParameters, ActualReturnTypeFlow actualReturn, BytecodeLocation location) {
585-
super(invokeLocation, receiverType, targetMethod, actualParameters, actualReturn, location);
586-
calleeContext = null;
587-
}
588-
589-
private BytecodeSensitiveStaticInvokeTypeFlow(PointsToAnalysis bb, MethodFlowsGraph methodFlows, BytecodeSensitiveStaticInvokeTypeFlow original) {
590-
super(bb, methodFlows, original);
591-
this.callerContext = ((MethodFlowsGraphClone) methodFlows).context();
592-
}
593-
594-
@Override
595-
public TypeFlow<BytecodePosition> copy(PointsToAnalysis bb, MethodFlowsGraph methodFlows) {
596-
return new BytecodeSensitiveStaticInvokeTypeFlow(bb, methodFlows, this);
597-
}
598-
599-
@Override
600-
public void update(PointsToAnalysis bb) {
601-
assert this.isClone();
602-
/* The static invokes should be updated only once and the callee should be null. */
603-
guarantee(callee == null, "static invoke updated multiple times!");
604-
605-
// Unlinked methods can not be parsed
606-
if (!targetMethod.getWrapped().getDeclaringClass().isLinked()) {
607-
return;
608-
}
609-
610-
/*
611-
* Initialize the callee lazily so that if the invoke flow is not reached in this
612-
* context, i.e. for this clone, there is no callee linked/
613-
*/
614-
callee = targetMethod.getTypeFlow();
615-
// set the callee in the original invoke too
616-
((DirectInvokeTypeFlow) originalInvoke).callee = callee;
617-
618-
calleeContext = contextPolicy(bb).staticCalleeContext(bb, location, (BytecodeAnalysisContext) callerContext, callee);
619-
MethodFlowsGraph calleeFlows = ((CallSiteSensitiveMethodTypeFlow) callee).addContext(bb, calleeContext, this);
620-
linkCallee(bb, true, calleeFlows);
621-
}
622-
623-
@Override
624-
public Collection<MethodFlowsGraph> getCalleesFlows(PointsToAnalysis bb) {
625-
if (callee == null || calleeContext == null) {
626-
/* This static invoke was not updated. */
627-
return Collections.emptyList();
628-
} else {
629-
MethodFlowsGraph methodFlows = ((CallSiteSensitiveMethodTypeFlow) callee).getFlows(calleeContext);
630-
return Collections.singletonList(methodFlows);
631-
}
632-
}
633-
}
634-
635-
private static final class BytecodeSensitiveSpecialInvokeTypeFlow extends AbstractSpecialInvokeTypeFlow {
636-
637-
/**
638-
* Contexts of the resolved method.
639-
*/
640-
private final ConcurrentMap<MethodFlowsGraph, Object> calleesFlows = new ConcurrentHashMap<>(4, 0.75f, 1);
641-
642-
/**
643-
* Context of the caller.
644-
*/
645-
private AnalysisContext callerContext;
646-
647-
BytecodeSensitiveSpecialInvokeTypeFlow(BytecodePosition invokeLocation, AnalysisType receiverType, PointsToAnalysisMethod targetMethod,
648-
TypeFlow<?>[] actualParameters, ActualReturnTypeFlow actualReturn, BytecodeLocation location) {
649-
super(invokeLocation, receiverType, targetMethod, actualParameters, actualReturn, location);
650-
}
651-
652-
private BytecodeSensitiveSpecialInvokeTypeFlow(PointsToAnalysis bb, MethodFlowsGraph methodFlows, BytecodeSensitiveSpecialInvokeTypeFlow original) {
653-
super(bb, methodFlows, original);
654-
this.callerContext = ((MethodFlowsGraphClone) methodFlows).context();
655-
}
656-
657-
@Override
658-
public TypeFlow<BytecodePosition> copy(PointsToAnalysis bb, MethodFlowsGraph methodFlows) {
659-
return new BytecodeSensitiveSpecialInvokeTypeFlow(bb, methodFlows, this);
660-
}
661-
662-
@Override
663-
public void onObservedUpdate(PointsToAnalysis bb) {
664-
/* The receiver state has changed. Process the invoke. */
665-
666-
initCallee();
667-
668-
TypeState invokeState = filterReceiverState(bb, getReceiver().getState());
669-
for (AnalysisObject receiverObject : invokeState.objects(bb)) {
670-
AnalysisContext calleeContext = contextPolicy(bb).calleeContext(bb, receiverObject, (BytecodeAnalysisContext) callerContext, callee);
671-
MethodFlowsGraph calleeFlows = ((CallSiteSensitiveMethodTypeFlow) callee).addContext(bb, calleeContext, this);
672-
673-
if (calleesFlows.putIfAbsent(calleeFlows, Boolean.TRUE) == null) {
674-
linkCallee(bb, false, calleeFlows);
675-
}
676-
677-
updateReceiver(bb, calleeFlows, receiverObject);
678-
}
679-
}
680-
681-
@Override
682-
public Collection<MethodFlowsGraph> getCalleesFlows(PointsToAnalysis bb) {
683-
return new ArrayList<>(calleesFlows.keySet());
684-
}
685-
}
686-
687384
@Override
688385
public TypeState forContextInsensitiveTypeState(PointsToAnalysis bb, TypeState state) {
689386
if (state.isEmpty() || state.isNull()) {

0 commit comments

Comments
 (0)