@Override public TypeFlow<ValueNode> copy(BigBang bb, MethodFlowsGraph methodFlows) { AnalysisContext enclosingContext = methodFlows.context(); AnalysisContext allocContext = bb.contextPolicy().allocationContext(enclosingContext, PointstoOptions.MaxHeapContextDepth.getValue(bb.getOptions())); return new CloneTypeFlow(bb, this, methodFlows, allocContext); }
@Override public void onObservedUpdate(BigBang bb) { /* Only a clone should be updated */ assert this.isClone() && context != null; /* The input state has changed, clone its objects. */ TypeState inputState = input.getState(); TypeState currentState = getState(); TypeState resultState; /* * The clone type flow creates a clone of it's input state. It intercepts the input state * and it creates a new state with the same types. The object abstractions can be the same * or different depending on the analysis policy. IF new heap objects are created they * encapsulate the location of the cloning. From the point of view of the analysis a clone * flow is a source. */ if (inputState.isEmpty() || inputState.isNull()) { /* Nothing to be cloned if the input state is not a concrete type state. */ resultState = inputState.forNonNull(bb); } else { resultState = inputState.typesStream() .filter(t -> !currentState.containsType(t)) .map(type -> TypeState.forClone(bb, source, cloneSite, type, allocationContext)) .reduce(TypeState.forEmpty(), (s1, s2) -> TypeState.forUnion(bb, s1, s2)); assert !resultState.canBeNull(); } /* Update the clone flow state. */ addState(bb, resultState); }
CloneTypeFlow cloneFlow = new CloneTypeFlow(node, cloneLabel, inputBuilder.get()); methodFlow.addClone(cloneFlow); return cloneFlow;