+ HierarchyGraph parentGraph = getHierarchyGraph(parentClassDescriptor);
+ HierarchyGraph childGraph = getHierarchyGraph(childClassDescriptor);
+
+ Set<HNode> parentNodeSet = parentGraph.getNodeSet();
+ for (Iterator iterator2 = parentNodeSet.iterator(); iterator2.hasNext();) {
+ HNode hNode = (HNode) iterator2.next();
+ childGraph.addNode(hNode);
+ }
+
+ // copies extra information from the parent hierarchy graph
+ Map<HNode, Set<HNode>> parentMergeNodeMap = parentGraph.getMapHNodetoMergeSet();
+ Map<HNode, Set<HNode>> childMergeNodeMap = childGraph.getMapHNodetoMergeSet();
+
+ Set<HNode> keySet = parentMergeNodeMap.keySet();
+ for (Iterator iterator2 = keySet.iterator(); iterator2.hasNext();) {
+ HNode parentKey = (HNode) iterator2.next();
+ if (!childMergeNodeMap.containsKey(parentKey)) {
+ childMergeNodeMap.put(parentKey, new HashSet<HNode>());
+ }
+ childMergeNodeMap.get(parentKey).addAll(parentMergeNodeMap.get(parentKey));
+ }
+
+ // copies nodes/edges from the parent class...
+ for (Iterator iterator2 = parentNodeSet.iterator(); iterator2.hasNext();) {
+ HNode parentHNode = (HNode) iterator2.next();
+
+ Set<HNode> parentIncomingHNode = parentGraph.getIncomingNodeSet(parentHNode);
+ Set<HNode> parentOutgoingHNode = parentGraph.getOutgoingNodeSet(parentHNode);
+
+ for (Iterator iterator3 = parentIncomingHNode.iterator(); iterator3.hasNext();) {
+ HNode inHNode = (HNode) iterator3.next();
+ childGraph.addEdge(inHNode.getDescriptor(), parentHNode.getDescriptor());
+ }
+
+ for (Iterator iterator3 = parentOutgoingHNode.iterator(); iterator3.hasNext();) {
+ HNode outHNode = (HNode) iterator3.next();
+ childGraph.addEdge(parentHNode.getDescriptor(), outHNode.getDescriptor());
+ }
+
+ }
+
+ // copies nodes/edges from parent methods to overridden methods
+
+ for (Iterator iterator3 = childClassDescriptor.getMethods(); iterator3.hasNext();) {
+ MethodDescriptor childMethodDescriptor = (MethodDescriptor) iterator3.next();
+
+ MethodDescriptor parentMethodDesc =
+ getParentMethodDesc(childMethodDescriptor.getClassDesc(), childMethodDescriptor);
+
+ if (parentMethodDesc != null) {
+
+ HierarchyGraph parentMethodGraph = getHierarchyGraph(parentMethodDesc);
+ HierarchyGraph childMethodGraph = getHierarchyGraph(childMethodDescriptor);
+
+ Set<HNode> parentMethodNodeSet = parentMethodGraph.getNodeSet();
+ for (Iterator iterator2 = parentMethodNodeSet.iterator(); iterator2.hasNext();) {
+ HNode hNode = (HNode) iterator2.next();
+ childMethodGraph.addNode(hNode);
+ }
+
+ // copies extra information from the parent hierarchy graph
+ Map<HNode, Set<HNode>> parentMethodMergeNodeMap =
+ parentMethodGraph.getMapHNodetoMergeSet();
+ Map<HNode, Set<HNode>> childMethodMergeNodeMap = childMethodGraph.getMapHNodetoMergeSet();
+
+ Set<HNode> methodKeySet = parentMethodMergeNodeMap.keySet();
+ for (Iterator iterator2 = methodKeySet.iterator(); iterator2.hasNext();) {
+ HNode parentKey = (HNode) iterator2.next();
+ if (!childMethodMergeNodeMap.containsKey(parentKey)) {
+ childMethodMergeNodeMap.put(parentKey, new HashSet<HNode>());
+ }
+ childMethodMergeNodeMap.get(parentKey).addAll(parentMethodMergeNodeMap.get(parentKey));
+ }
+
+ // copies nodes/edges from the parent method...
+ for (Iterator iterator2 = parentMethodGraph.getNodeSet().iterator(); iterator2.hasNext();) {
+ HNode parentHNode = (HNode) iterator2.next();
+
+ Set<HNode> parentIncomingHNode = parentMethodGraph.getIncomingNodeSet(parentHNode);
+ Set<HNode> parentOutgoingHNode = parentMethodGraph.getOutgoingNodeSet(parentHNode);
+
+ for (Iterator iterator4 = parentIncomingHNode.iterator(); iterator4.hasNext();) {
+ HNode inHNode = (HNode) iterator4.next();
+ childMethodGraph.addEdge(inHNode, parentHNode);
+ }
+
+ for (Iterator iterator4 = parentOutgoingHNode.iterator(); iterator4.hasNext();) {
+ HNode outHNode = (HNode) iterator4.next();
+ childMethodGraph.addEdge(parentHNode, outHNode);
+ }
+
+ }
+
+ }
+
+ }
+
+ DFSInheritanceTree(childClassDescriptor);
+ }
+
+ }
+
+ public MethodDescriptor getParentMethodDesc(ClassDescriptor classDesc, MethodDescriptor methodDesc) {
+
+ // Node<ClassDescriptor> childNode = inheritanceTree.getTreeNode(classDesc);
+ ClassDescriptor parentClassDesc = classDesc.getSuperDesc();
+ // Node<ClassDescriptor> parentNode = childNode.getParent();
+
+ if (parentClassDesc != null) {
+ // ClassDescriptor parentClassDesc = parentNode.getData();
+ if (parentClassDesc.getMethodTable().contains(methodDesc.getSymbol())) {
+ Set<MethodDescriptor> methodDescSet =
+ parentClassDesc.getMethodTable().getSet(methodDesc.getSymbol());
+ for (Iterator iterator = methodDescSet.iterator(); iterator.hasNext();) {
+ MethodDescriptor md = (MethodDescriptor) iterator.next();
+ if (md.matches(methodDesc)) {
+ return md;
+ }
+ }
+ }
+
+ // traverse to the parent!
+ getParentMethodDesc(parentClassDesc, methodDesc);
+
+ }
+
+ return null;
+ }
+
+ private void checkReturnNodes() {
+ LinkedList<MethodDescriptor> methodDescList =
+ (LinkedList<MethodDescriptor>) toanalyze_methodDescList.clone();
+
+ while (!methodDescList.isEmpty()) {
+ MethodDescriptor md = methodDescList.removeLast();
+
+ if (md.getReturnType() != null && !md.getReturnType().isVoid()) {
+ checkFlowNodeReturnThisField(md);
+ }
+ // // in this case, this method will return the composite location that starts with 'this'
+ // FlowGraph flowGraph = getFlowGraph(md);
+ // Set<FlowNode> returnNodeSet = flowGraph.getReturnNodeSet();
+ // }
+
+ }
+
+ }
+
+ private void addSuperClasses(ClassDescriptor cd) {
+ ClassDescriptor parentClassDesc = cd.getSuperDesc();
+ if (parentClassDesc != null) {
+ toanalyze_classDescSet.add(parentClassDesc);
+ addSuperClasses(parentClassDesc);
+ }
+ }
+
+ private void updateFlowGraph() {
+
+ LinkedList<MethodDescriptor> methodDescList =
+ (LinkedList<MethodDescriptor>) toanalyze_methodDescList.clone();
+
+ while (!methodDescList.isEmpty()) {
+ MethodDescriptor md = methodDescList.removeLast();
+ if (state.SSJAVADEBUG) {
+ System.out.println();
+ System.out.println("SSJAVA: Updating a flow graph: " + md);
+ propagateFlowsFromCalleesWithNoCompositeLocation(md);
+ }
+
+ Set<FlowNode> nodeSet = getFlowGraph(md).getNodeSet();
+ for (Iterator iterator = nodeSet.iterator(); iterator.hasNext();) {
+ FlowNode flowNode = (FlowNode) iterator.next();
+ NTuple<Descriptor> descTuple = flowNode.getCurrentDescTuple();
+ NTuple<Location> locTuple = translateToLocTuple(md, descTuple);
+ for (int i = 0; i < locTuple.size(); i++) {
+ Location loc = locTuple.get(i);
+ if (loc.getDescriptor() instanceof ClassDescriptor) {
+ ClassDescriptor classDesc = (ClassDescriptor) loc.getDescriptor();
+ toanalyze_classDescSet.add(classDesc);
+ addSuperClasses(classDesc);
+ } else if (loc.getDescriptor() instanceof MethodDescriptor) {
+ toanalyze_classDescSet.add(((MethodDescriptor) loc.getDescriptor()).getClassDesc());
+ }
+ }
+
+ }
+
+ }
+ }
+
+ public Map<NTuple<Descriptor>, NTuple<Descriptor>> getMapCallerArgToCalleeParam(
+ MethodInvokeNode min) {
+
+ if (!mapMethodInvokeNodeToMapCallerArgToCalleeArg.containsKey(min)) {
+ mapMethodInvokeNodeToMapCallerArgToCalleeArg.put(min,
+ new HashMap<NTuple<Descriptor>, NTuple<Descriptor>>());
+ }
+
+ return mapMethodInvokeNodeToMapCallerArgToCalleeArg.get(min);
+ }
+
+ public void addMapCallerArgToCalleeParam(MethodInvokeNode min, NTuple<Descriptor> callerArg,
+ NTuple<Descriptor> calleeParam) {
+ getMapCallerArgToCalleeParam(min).put(callerArg, calleeParam);
+ }
+
+ private void assignCompositeLocation() {
+ calculateGlobalValueFlowCompositeLocation();
+ translateCompositeLocationAssignmentToFlowGraph();
+ }
+
+ private void translateCompositeLocationAssignmentToFlowGraph() {
+ System.out.println("\nSSJAVA: Translate composite location assignments to flow graphs:");
+ MethodDescriptor methodEventLoopDesc = ssjava.getMethodContainingSSJavaLoop();
+ translateCompositeLocationAssignmentToFlowGraph(methodEventLoopDesc);
+ }
+
+ private void translateCompositeLocationAssignmentToFlowGraph2() {
+ System.out.println("\nSSJAVA: Translate composite location assignments to flow graphs:");
+ MethodDescriptor methodEventLoopDesc = ssjava.getMethodContainingSSJavaLoop();
+ translateCompositeLocationAssignmentToFlowGraph(methodEventLoopDesc);
+ }
+
+ private void addAdditionalOrderingConstraints() {
+ System.out.println("\nSSJAVA: Add addtional ordering constriants:");
+ MethodDescriptor methodEventLoopDesc = ssjava.getMethodContainingSSJavaLoop();
+ addAddtionalOrderingConstraints(methodEventLoopDesc);
+ // calculateReturnHolderLocation();
+ }
+
+ private void calculateReturnHolderLocation() {
+ LinkedList<MethodDescriptor> methodDescList =
+ (LinkedList<MethodDescriptor>) toanalyze_methodDescList.clone();
+
+ while (!methodDescList.isEmpty()) {
+ MethodDescriptor md = methodDescList.removeLast();
+
+ FlowGraph fg = getFlowGraph(md);
+ Set<FlowNode> nodeSet = fg.getNodeSet();
+ for (Iterator iterator = nodeSet.iterator(); iterator.hasNext();) {
+ FlowNode flowNode = (FlowNode) iterator.next();
+ if (flowNode.isFromHolder()) {
+ calculateCompositeLocationFromFlowGraph(md, flowNode);
+ }
+ }
+
+ }
+ }
+
+ private void updateCompositeLocationAssignments() {
+
+ LinkedList<MethodDescriptor> methodDescList =
+ (LinkedList<MethodDescriptor>) toanalyze_methodDescList.clone();
+
+ while (!methodDescList.isEmpty()) {
+ MethodDescriptor md = methodDescList.removeLast();
+
+ // System.out.println("\n#updateCompositeLocationAssignments=" + md);
+
+ FlowGraph flowGraph = getFlowGraph(md);
+
+ MethodSummary methodSummary = getMethodSummary(md);
+
+ Set<FlowNode> nodeSet = flowGraph.getNodeSet();
+ for (Iterator iterator = nodeSet.iterator(); iterator.hasNext();) {
+ FlowNode node = (FlowNode) iterator.next();
+ // System.out.println("-node=" + node + " node.getDescTuple=" + node.getDescTuple());
+ if (node.getCompositeLocation() != null) {
+ CompositeLocation compLoc = node.getCompositeLocation();
+ CompositeLocation updatedCompLoc = updateCompositeLocation(compLoc);
+ node.setCompositeLocation(updatedCompLoc);
+ // System.out.println("---updatedCompLoc1=" + updatedCompLoc);
+ } else {
+ NTuple<Descriptor> descTuple = node.getDescTuple();
+ // System.out.println("update desc=" + descTuple);
+ CompositeLocation compLoc = convertToCompositeLocation(md, descTuple);
+ compLoc = updateCompositeLocation(compLoc);
+ node.setCompositeLocation(compLoc);
+ // System.out.println("---updatedCompLoc2=" + compLoc);
+ }
+
+ if (node.isDeclaratonNode()) {
+ Descriptor localVarDesc = node.getDescTuple().get(0);
+ CompositeLocation compLoc = updateCompositeLocation(node.getCompositeLocation());
+ methodSummary.addMapVarNameToInferCompLoc(localVarDesc, compLoc);
+ }
+ }
+
+ // update PCLOC and RETURNLOC if they have a composite location assignment
+ if (methodSummary.getRETURNLoc() != null) {
+ methodSummary.setRETURNLoc(updateCompositeLocation(methodSummary.getRETURNLoc()));
+ }
+ if (methodSummary.getPCLoc() != null) {
+ methodSummary.setPCLoc(updateCompositeLocation(methodSummary.getPCLoc()));
+ }
+
+ }
+
+ }
+
+ private CompositeLocation updateCompositeLocation(CompositeLocation compLoc) {
+ CompositeLocation updatedCompLoc = new CompositeLocation();
+ for (int i = 0; i < compLoc.getSize(); i++) {
+ Location loc = compLoc.get(i);
+ String nodeIdentifier = loc.getLocIdentifier();
+ Descriptor enclosingDesc = loc.getDescriptor();
+ String locName;
+ if (!enclosingDesc.equals(GLOBALDESC)) {
+ LocationSummary locSummary = getLocationSummary(enclosingDesc);
+ // HierarchyGraph scGraph = getSkeletonCombinationHierarchyGraph(enclosingDesc);
+ HierarchyGraph scGraph = getSimpleHierarchyGraph(enclosingDesc);
+ if (scGraph != null) {
+ HNode curNode = scGraph.getCurrentHNode(nodeIdentifier);
+ // System.out.println("nodeID=" + nodeIdentifier + " curNode=" + curNode
+ // + " enclosingDesc=" + enclosingDesc);
+ if (curNode != null) {
+ nodeIdentifier = curNode.getName();
+ }
+ }
+ locName = locSummary.getLocationName(nodeIdentifier);
+ } else {
+ locName = nodeIdentifier;
+ }
+ Location updatedLoc = new Location(enclosingDesc, locName);
+ updatedCompLoc.addLocation(updatedLoc);
+ }
+
+ return updatedCompLoc;
+ }
+
+ private void translateCompositeLocationAssignmentToFlowGraph(MethodDescriptor mdCaller) {
+
+ // System.out.println("\n\n###translateCompositeLocationAssignmentToFlowGraph mdCaller="
+ // + mdCaller);
+
+ // First, assign a composite location to a node in the flow graph
+ GlobalFlowGraph callerGlobalFlowGraph = getSubGlobalFlowGraph(mdCaller);
+
+ FlowGraph callerFlowGraph = getFlowGraph(mdCaller);
+ Map<Location, CompositeLocation> callerMapLocToCompLoc =
+ callerGlobalFlowGraph.getMapLocationToInferCompositeLocation();
+
+ Set<Location> methodLocSet = callerMapLocToCompLoc.keySet();
+ for (Iterator iterator = methodLocSet.iterator(); iterator.hasNext();) {
+ Location methodLoc = (Location) iterator.next();
+ if (methodLoc.getDescriptor().equals(mdCaller)) {
+ CompositeLocation inferCompLoc = callerMapLocToCompLoc.get(methodLoc);
+ assignCompositeLocationToFlowGraph(callerFlowGraph, methodLoc, inferCompLoc);
+ }
+ }
+
+ Set<MethodInvokeNode> minSet = mapMethodDescriptorToMethodInvokeNodeSet.get(mdCaller);
+
+ Set<MethodDescriptor> calleeSet = new HashSet<MethodDescriptor>();
+ for (Iterator iterator = minSet.iterator(); iterator.hasNext();) {
+ MethodInvokeNode min = (MethodInvokeNode) iterator.next();
+ // need to translate a composite location that is started with the base
+ // tuple of 'min'.
+ translateMapLocationToInferCompositeLocationToCalleeGraph(callerGlobalFlowGraph, min);
+ MethodDescriptor mdCallee = min.getMethod();
+ calleeSet.add(mdCallee);
+
+ }
+
+ for (Iterator iterator = calleeSet.iterator(); iterator.hasNext();) {
+ MethodDescriptor callee = (MethodDescriptor) iterator.next();
+ translateCompositeLocationAssignmentToFlowGraph(callee);
+ }
+
+ }
+
+ private void addAddtionalOrderingConstraints(MethodDescriptor mdCaller) {
+
+ // First, assign a composite location to a node in the flow graph
+ GlobalFlowGraph callerGlobalFlowGraph = getSubGlobalFlowGraph(mdCaller);
+
+ FlowGraph callerFlowGraph = getFlowGraph(mdCaller);
+ Map<Location, CompositeLocation> callerMapLocToCompLoc =
+ callerGlobalFlowGraph.getMapLocationToInferCompositeLocation();
+ Set<Location> methodLocSet = callerMapLocToCompLoc.keySet();
+
+ Set<MethodInvokeNode> minSet = mapMethodDescriptorToMethodInvokeNodeSet.get(mdCaller);
+
+ Set<MethodDescriptor> calleeSet = new HashSet<MethodDescriptor>();
+ for (Iterator iterator = minSet.iterator(); iterator.hasNext();) {
+ MethodInvokeNode min = (MethodInvokeNode) iterator.next();
+ MethodDescriptor mdCallee = min.getMethod();
+ calleeSet.add(mdCallee);
+
+ //
+ // add an additional ordering constraint
+ // if the first element of a parameter composite location matches 'this' reference,
+ // the corresponding argument in the caller is required to be higher than the translated
+ // parameter location in the caller lattice
+ // TODO
+ // addOrderingConstraintFromCompLocParamToArg(mdCaller, min);
+
+ //
+ // update return flow nodes in the caller
+ CompositeLocation returnLoc = getMethodSummary(mdCallee).getRETURNLoc();
+ // System.out.println("### min=" + min.printNode(0) + " returnLoc=" + returnLoc);
+ if (returnLoc != null && returnLoc.get(0).getLocDescriptor().equals(mdCallee.getThis())
+ && returnLoc.getSize() > 1) {
+ // System.out.println("###RETURN COMP LOC=" + returnLoc);
+ NTuple<Location> returnLocTuple = returnLoc.getTuple();
+ NTuple<Descriptor> baseTuple = mapMethodInvokeNodeToBaseTuple.get(min);
+ // System.out.println("###basetuple=" + baseTuple);
+ NTuple<Descriptor> newReturnTuple = baseTuple.clone();
+ for (int i = 1; i < returnLocTuple.size(); i++) {
+ newReturnTuple.add(returnLocTuple.get(i).getLocDescriptor());
+ }
+ // System.out.println("###NEW RETURN TUPLE FOR CALLER=" + newReturnTuple);
+
+ FlowReturnNode holderNode = callerFlowGraph.getFlowReturnNode(min);
+ NodeTupleSet holderTupleSet =
+ getNodeTupleSetFromReturnNode(getFlowGraph(mdCaller), holderNode);
+
+ callerFlowGraph.getFlowReturnNode(min).setNewTuple(newReturnTuple);
+
+ // then need to remove old constraints
+ // TODO SAT
+ // System.out.println("###REMOVE OLD CONSTRAINTS=" + holderNode);
+ for (Iterator<NTuple<Descriptor>> iter = holderTupleSet.iterator(); iter.hasNext();) {
+ NTuple<Descriptor> tupleFromHolder = iter.next();
+ Set<FlowEdge> holderOutEdge = callerFlowGraph.getOutEdgeSet(holderNode);
+ for (Iterator iterator2 = holderOutEdge.iterator(); iterator2.hasNext();) {
+ FlowEdge outEdge = (FlowEdge) iterator2.next();
+ NTuple<Descriptor> toberemovedTuple = outEdge.getEndTuple();
+ // System.out.println("---remove " + tupleFromHolder + " -> " + toberemovedTuple);
+ callerFlowGraph.removeEdge(tupleFromHolder, toberemovedTuple);
+ }
+ }
+
+ } else {
+ // if the return loc set was empty and later pcloc was connected to the return loc
+ // need to make sure that return loc reflects to this changes.
+ FlowReturnNode flowReturnNode = callerFlowGraph.getFlowReturnNode(min);
+ if (flowReturnNode != null && flowReturnNode.getReturnTupleSet().isEmpty()) {
+
+ if (needToUpdateReturnLocHolder(min.getMethod(), flowReturnNode)) {
+ NTuple<Descriptor> baseTuple = mapMethodInvokeNodeToBaseTuple.get(min);
+ NTuple<Descriptor> newReturnTuple = baseTuple.clone();
+ flowReturnNode.addTuple(newReturnTuple);
+ }
+
+ }
+
+ }
+
+ }
+
+ for (Iterator iterator = calleeSet.iterator(); iterator.hasNext();) {
+ MethodDescriptor callee = (MethodDescriptor) iterator.next();
+ addAddtionalOrderingConstraints(callee);
+ }
+
+ }
+
+ private boolean needToUpdateReturnLocHolder(MethodDescriptor mdCallee,
+ FlowReturnNode flowReturnNode) {
+ FlowGraph fg = getFlowGraph(mdCallee);
+ MethodSummary summary = getMethodSummary(mdCallee);
+ CompositeLocation returnCompLoc = summary.getRETURNLoc();
+ NTuple<Descriptor> returnDescTuple = translateToDescTuple(returnCompLoc.getTuple());
+ Set<FlowNode> incomingNodeToReturnNode =
+ fg.getIncomingFlowNodeSet(fg.getFlowNode(returnDescTuple));
+ for (Iterator iterator = incomingNodeToReturnNode.iterator(); iterator.hasNext();) {
+ FlowNode inNode = (FlowNode) iterator.next();
+ if (inNode.getDescTuple().get(0).equals(mdCallee.getThis())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void addMapMethodDescToMethodInvokeNodeSet(MethodInvokeNode min) {
+ MethodDescriptor md = min.getMethod();
+ if (!mapMethodDescToMethodInvokeNodeSet.containsKey(md)) {
+ mapMethodDescToMethodInvokeNodeSet.put(md, new HashSet<MethodInvokeNode>());
+ }
+ mapMethodDescToMethodInvokeNodeSet.get(md).add(min);
+ }
+
+ private Set<MethodInvokeNode> getMethodInvokeNodeSetByMethodDesc(MethodDescriptor md) {
+ if (!mapMethodDescToMethodInvokeNodeSet.containsKey(md)) {
+ mapMethodDescToMethodInvokeNodeSet.put(md, new HashSet<MethodInvokeNode>());
+ }
+ return mapMethodDescToMethodInvokeNodeSet.get(md);
+ }
+
+ public void assignCompositeLocationToFlowGraph(FlowGraph flowGraph, Location loc,
+ CompositeLocation inferCompLoc) {
+ Descriptor localDesc = loc.getLocDescriptor();
+
+ Set<FlowNode> nodeSet = flowGraph.getNodeSet();
+ for (Iterator iterator = nodeSet.iterator(); iterator.hasNext();) {
+ FlowNode node = (FlowNode) iterator.next();
+ if (node.getDescTuple().startsWith(localDesc)
+ && !node.getDescTuple().get(0).equals(LITERALDESC)) {
+ // need to assign the inferred composite location to this node
+ CompositeLocation newCompLoc = generateCompositeLocation(node.getDescTuple(), inferCompLoc);
+ node.setCompositeLocation(newCompLoc);
+ // System.out.println("SET Node=" + node + " inferCompLoc=" + newCompLoc);
+ }
+ }
+ }
+
+ private CompositeLocation generateCompositeLocation(NTuple<Descriptor> nodeDescTuple,
+ CompositeLocation inferCompLoc) {
+
+ // System.out.println("generateCompositeLocation=" + nodeDescTuple + " with inferCompLoc="
+ // + inferCompLoc);
+
+ MethodDescriptor md = (MethodDescriptor) inferCompLoc.get(0).getDescriptor();
+
+ CompositeLocation newCompLoc = new CompositeLocation();
+ for (int i = 0; i < inferCompLoc.getSize(); i++) {
+ newCompLoc.addLocation(inferCompLoc.get(i));
+ }
+
+ Descriptor lastDescOfPrefix = nodeDescTuple.get(0);
+ Descriptor enclosingDescriptor;
+ if (lastDescOfPrefix instanceof InterDescriptor) {
+ enclosingDescriptor = getFlowGraph(md).getEnclosingDescriptor(lastDescOfPrefix);
+ } else {
+ enclosingDescriptor = ((VarDescriptor) lastDescOfPrefix).getType().getClassDesc();
+ }
+
+ for (int i = 1; i < nodeDescTuple.size(); i++) {
+ Descriptor desc = nodeDescTuple.get(i);
+ Location locElement = new Location(enclosingDescriptor, desc);
+ newCompLoc.addLocation(locElement);
+
+ enclosingDescriptor = ((FieldDescriptor) desc).getClassDescriptor();
+ }
+
+ return newCompLoc;
+ }
+
+ private void translateMapLocationToInferCompositeLocationToCalleeGraph(
+ GlobalFlowGraph callerGraph, MethodInvokeNode min) {
+
+ MethodDescriptor mdCallee = min.getMethod();
+ MethodDescriptor mdCaller = callerGraph.getMethodDescriptor();
+ Map<Location, CompositeLocation> callerMapLocToCompLoc =
+ callerGraph.getMapLocationToInferCompositeLocation();
+
+ Map<Integer, NTuple<Descriptor>> mapIdxToArgTuple = mapMethodInvokeNodeToArgIdxMap.get(min);
+
+ FlowGraph calleeFlowGraph = getFlowGraph(mdCallee);
+ GlobalFlowGraph calleeGlobalGraph = getSubGlobalFlowGraph(mdCallee);
+
+ NTuple<Location> baseLocTuple = null;
+ if (mapMethodInvokeNodeToBaseTuple.containsKey(min)) {
+ baseLocTuple = translateToLocTuple(mdCaller, mapMethodInvokeNodeToBaseTuple.get(min));
+ }
+
+ // System.out.println("\n-#translate caller=" + mdCaller + " infer composite loc to callee="
+ // + mdCallee + " baseLocTuple=" + baseLocTuple);
+
+ Set<Location> keySet = callerMapLocToCompLoc.keySet();
+ for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
+ Location key = (Location) iterator.next();
+ CompositeLocation callerCompLoc = callerMapLocToCompLoc.get(key);
+
+ if (!key.getDescriptor().equals(mdCaller)) {
+
+ CompositeLocation newCalleeCompLoc;
+ if (baseLocTuple != null && callerCompLoc.getTuple().startsWith(baseLocTuple)) {
+ // System.out.println("-----need to translate callerCompLoc=" + callerCompLoc
+ // + " with baseTuple=" + baseLocTuple);