+ private void calculateReturnPCLocInheritance() {
+ calculateHighestPCLocInheritance();
+ calculateLowestReturnLocInheritance();
+ updateFlowGraphPCReturnLocInheritance();
+ }
+
+ private void updateFlowGraphPCReturnLocInheritance() {
+ Set<MethodDescriptor> keySet = mapHighestOverriddenMethodDescToMethodDescSet.keySet();
+ for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
+ MethodDescriptor highestMethodDesc = (MethodDescriptor) iterator.next();
+
+ if (mapHighestOverriddenMethodDescToMethodDescSet.get(highestMethodDesc).size() == 1) {
+ continue;
+ }
+
+ Set<MethodDescriptor> methodDescSet =
+ mapHighestOverriddenMethodDescToMethodDescSet.get(highestMethodDesc);
+
+ NTuple<Descriptor> highestPCLoc =
+ mapHighestOverriddenMethodDescToPCLocTuple.get(highestMethodDesc);
+
+ NTuple<Descriptor> highestRETURNLoc =
+ mapHighestOverriddenMethodDescToReturnLocTuple.get(highestMethodDesc);
+
+ System.out.println("---highestMethodDesc=" + highestMethodDesc);
+
+ for (Iterator iterator2 = methodDescSet.iterator(); iterator2.hasNext();) {
+ MethodDescriptor md = (MethodDescriptor) iterator2.next();
+ FlowGraph flowGraph = getFlowGraph(md);
+
+ MethodSummary summary = getMethodSummary(md);
+ CompositeLocation curPCLoc = summary.getPCLoc();
+
+ // update PCLOC
+ if (highestPCLoc != null) {
+ // handle the case that PCLOC is started with 'this'...
+ NTuple<Descriptor> newPCLoc = new NTuple<Descriptor>();
+ if (highestPCLoc.size() == 1) {
+ newPCLoc.add(highestPCLoc.get(0));
+ } else {
+ newPCLoc.add(md.getThis());
+ newPCLoc.add(highestPCLoc.get(1));
+ }
+
+ FlowNode pcFlowNode = flowGraph.getFlowNode(translateToDescTuple(curPCLoc.getTuple()));
+ pcFlowNode.setBaseTuple(newPCLoc);
+
+ CompositeLocation newPCLocCompLoc =
+ new CompositeLocation(translateToLocTuple(md, newPCLoc));
+ summary.setPCLoc(newPCLocCompLoc);
+ } else {
+ // need to remove PCLOC if the overridden method defines it
+ if (curPCLoc != null && !curPCLoc.get(0).isTop()) {
+ System.out.println("md=" + md + " curPCLoc=" + curPCLoc);
+ FlowNode pcFlowNode = flowGraph.getFlowNode(translateToDescTuple(curPCLoc.getTuple()));
+ System.out.println("#######REMOVE PCLOCNODE=" + pcFlowNode);
+ flowGraph.removeNode(pcFlowNode);
+ }
+ }
+
+ // need to update RETURNLOC
+ if (highestRETURNLoc != null) {
+
+ CompositeLocation curRETURNLoc = summary.getRETURNLoc();
+ System.out.println("curRETURNLoc=" + curRETURNLoc);
+
+ // handle the case that RETURNLOC is started with 'this'...
+ NTuple<Descriptor> newRETURNLoc = new NTuple<Descriptor>();
+ if (highestRETURNLoc.size() == 1) {
+ newRETURNLoc.add(highestRETURNLoc.get(0));
+ } else {
+ newRETURNLoc.add(md.getThis());
+ newRETURNLoc.add(highestRETURNLoc.get(1));
+ }
+
+ FlowNode returnFlowNode =
+ flowGraph.getFlowNode(translateToDescTuple(curRETURNLoc.getTuple()));
+ returnFlowNode.setBaseTuple(newRETURNLoc);
+
+ CompositeLocation newRETURNLocCompLoc =
+ new CompositeLocation(translateToLocTuple(md, newRETURNLoc));
+ summary.setPCLoc(newRETURNLocCompLoc);
+ System.out.println("md=" + md + "###newRETURNLocCompLoc=" + newRETURNLocCompLoc);
+
+ }
+
+ }
+ }
+ }
+
+ private void calculateHighestPCLocInheritance() {
+
+ Set<MethodDescriptor> keySet = mapHighestOverriddenMethodDescToMethodDescSet.keySet();
+ next: for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
+ MethodDescriptor highestMethodDesc = (MethodDescriptor) iterator.next();
+
+ NTuple<Descriptor> tempTuple = null;
+
+ if (getMethodSummary(highestMethodDesc).getPCLoc() != null) {
+
+ Set<MethodDescriptor> methodDescSet =
+ mapHighestOverriddenMethodDescToMethodDescSet.get(highestMethodDesc);
+
+ for (Iterator iterator2 = methodDescSet.iterator(); iterator2.hasNext();) {
+ MethodDescriptor md = (MethodDescriptor) iterator2.next();
+
+ FlowGraph flowGraph = getFlowGraph(md);
+ if (flowGraph == null) {
+ continue;
+ }
+ Set<FlowNode> paramNodeSet = flowGraph.getParamFlowNodeSet();
+ System.out.println("###md=" + md + " paramNodeSet=" + paramNodeSet);
+
+ CompositeLocation pcLOC = getMethodSummary(md).getPCLoc();
+
+ if (!pcLOC.get(0).isTop()) {
+ if (pcLOC.getSize() == 1) {
+ // return location is not started with 'this'
+ // check whether the return location is lower than all parameters.
+
+ FlowNode pcFlowNode = flowGraph.getFlowNode(translateToDescTuple(pcLOC.getTuple()));
+
+ int count = 0;
+ for (Iterator iterator3 = paramNodeSet.iterator(); iterator3.hasNext();) {
+ FlowNode paramNode = (FlowNode) iterator3.next();
+ if (flowGraph.getReachableSetFrom(pcFlowNode.getCurrentDescTuple().subList(0, 1))
+ .contains(paramNode)) {
+ count++;
+ System.out.println("-------" + pcFlowNode + " -> " + paramNode);
+ }
+ }
+
+ int offset = 0;
+ if (!md.isStatic()) {
+ offset = 1;
+ }
+
+ NTuple<Descriptor> rTuple = new NTuple<Descriptor>();
+ rTuple.add(pcLOC.get(0).getLocDescriptor());
+ if (count == (md.numParameters() + offset)) {
+ // means return loc is lower than a composite location starting with 'this'
+ mapHighestOverriddenMethodDescToPCLocTuple.put(highestMethodDesc, rTuple);
+ } else {
+ if (tempTuple == null) {
+ tempTuple = rTuple;
+ }
+ }
+ } else {
+ // if the current overridden method has a composite pc loc(size>1)
+ // and it has not yet finalized the pc location,
+ // the highest overridden method would have the composite pc location starting with
+ // 'this'
+ NTuple<Descriptor> rTuple = new NTuple<Descriptor>();
+ for (int i = 0; i < pcLOC.getSize(); i++) {
+ rTuple.add(pcLOC.get(i).getLocDescriptor());
+ }
+ tempTuple = rTuple;
+ }
+ } else {
+ mapHighestOverriddenMethodDescToPCLocTuple.remove(highestMethodDesc);
+ System.out.println("highest=" + highestMethodDesc + " HIGHEST PCLOC="
+ + mapHighestOverriddenMethodDescToPCLocTuple.get(highestMethodDesc));
+ continue next;
+ }
+ }
+
+ }
+
+ if (!mapHighestOverriddenMethodDescToPCLocTuple.containsKey(highestMethodDesc)
+ && tempTuple != null) {
+ mapHighestOverriddenMethodDescToPCLocTuple.put(highestMethodDesc, tempTuple);
+ }
+ System.out.println("highest=" + highestMethodDesc + " HIGHEST PCLOC="
+ + mapHighestOverriddenMethodDescToPCLocTuple.get(highestMethodDesc));
+ }
+
+ }
+
+ private void calculateLowestReturnLocInheritance() {
+
+ Set<MethodDescriptor> keySet = mapHighestOverriddenMethodDescToMethodDescSet.keySet();
+ for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
+ MethodDescriptor highestMethodDesc = (MethodDescriptor) iterator.next();
+
+ NTuple<Descriptor> tempTuple = null;
+
+ if (getMethodSummary(highestMethodDesc).getRETURNLoc() != null) {
+ Set<MethodDescriptor> methodDescSet =
+ mapHighestOverriddenMethodDescToMethodDescSet.get(highestMethodDesc);
+ for (Iterator iterator2 = methodDescSet.iterator(); iterator2.hasNext();) {
+ MethodDescriptor md = (MethodDescriptor) iterator2.next();
+
+ FlowGraph flowGraph = getFlowGraph(md);
+ Set<FlowNode> paramNodeSet = flowGraph.getParamFlowNodeSet();
+ System.out.println("###md=" + md + " paramNodeSet=" + paramNodeSet);
+
+ CompositeLocation returnLoc = getMethodSummary(md).getRETURNLoc();
+ if (returnLoc.getSize() == 1) {
+ // return location is not started with 'this'
+ // check whether the return location is lower than all parameters.
+
+ FlowNode returnFlowNode =
+ flowGraph.getFlowNode(translateToDescTuple(returnLoc.getTuple()));
+
+ int count = 0;
+ for (Iterator iterator3 = paramNodeSet.iterator(); iterator3.hasNext();) {
+ FlowNode paramNode = (FlowNode) iterator3.next();
+ if (flowGraph.getReachableSetFrom(paramNode.getCurrentDescTuple().subList(0, 1))
+ .contains(returnFlowNode)) {
+ count++;
+ System.out.println("-------" + paramNode + " -> " + returnFlowNode);
+ }
+ }
+
+ int offset = 0;
+ if (!md.isStatic()) {
+ offset = 1;
+ }
+
+ NTuple<Descriptor> rTuple = new NTuple<Descriptor>();
+ rTuple.add(returnLoc.get(0).getLocDescriptor());
+ if (count == (md.numParameters() + offset)) {
+ // means return loc is lower than a composite location starting with 'this'
+ mapHighestOverriddenMethodDescToReturnLocTuple.put(highestMethodDesc, rTuple);
+ } else {
+ if (tempTuple == null) {
+ tempTuple = rTuple;
+ }
+ }
+ } else {
+ // if the current overridden method has a composite return loc(size>1)
+ // and it has not yet finalized the return location
+ // the highest overridden method has the composite return location starting with
+ // 'this'
+ NTuple<Descriptor> rTuple = new NTuple<Descriptor>();
+ for (int i = 0; i < returnLoc.getSize(); i++) {
+ rTuple.add(returnLoc.get(i).getLocDescriptor());
+ }
+ tempTuple = rTuple;
+ }
+
+ }
+
+ }
+
+ if (!mapHighestOverriddenMethodDescToReturnLocTuple.containsKey(highestMethodDesc)
+ && tempTuple != null) {
+ mapHighestOverriddenMethodDescToReturnLocTuple.put(highestMethodDesc, tempTuple);
+ }
+ System.out.println("highest=" + highestMethodDesc + " rTuple="
+ + mapHighestOverriddenMethodDescToReturnLocTuple.get(highestMethodDesc));
+ }
+
+ }
+
+ private void addMapHighestMethodDescToMethodDesc(MethodDescriptor highest, MethodDescriptor md) {
+ if (!mapHighestOverriddenMethodDescToMethodDescSet.containsKey(highest)) {
+ mapHighestOverriddenMethodDescToMethodDescSet.put(highest, new HashSet<MethodDescriptor>());
+ }
+ mapHighestOverriddenMethodDescToMethodDescSet.get(highest).add(md);
+ }
+
+ private void DFSInheritanceTreeCalculatingHighestOverriddenMethod(ClassDescriptor cd) {
+
+ // ClassDescriptor cd = node.getData();
+
+ for (Iterator iterator = cd.getMethods(); iterator.hasNext();) {
+ MethodDescriptor md = (MethodDescriptor) iterator.next();
+ MethodDescriptor highestMethodDesc = getHighestOverriddenMethod(md.getClassDesc(), md);
+ mapMethodDescToHighestOverriddenMethodDesc.put(md, highestMethodDesc);
+ addMapHighestMethodDescToMethodDesc(highestMethodDesc, md);
+
+ }
+
+ // traverse children
+ Set<ClassDescriptor> children = getDirectSubClasses(cd);
+ for (Iterator iterator = children.iterator(); iterator.hasNext();) {
+ ClassDescriptor child = (ClassDescriptor) iterator.next();
+ DFSInheritanceTreeCalculatingHighestOverriddenMethod(child);
+ }
+
+ }
+
+ private MethodDescriptor getHighestOverriddenMethod(ClassDescriptor curClassDesc,
+ MethodDescriptor curMethodDesc) {
+
+ // Node<ClassDescriptor> curNode = inheritanceTree.getTreeNode(curClassDesc);
+ // Node<ClassDescriptor> parentNode = curNode.getParent();
+ ClassDescriptor parentClassDesc = curClassDesc.getSuperDesc();
+
+ if (parentClassDesc != null) {
+ if (parentClassDesc.getMethodTable().contains(curMethodDesc.getSymbol())) {
+ Set<MethodDescriptor> methodDescSet =
+ parentClassDesc.getMethodTable().getSet(curMethodDesc.getSymbol());
+ for (Iterator iterator = methodDescSet.iterator(); iterator.hasNext();) {
+ MethodDescriptor md = (MethodDescriptor) iterator.next();
+ if (md.matches(curMethodDesc)) {
+ return getHighestOverriddenMethod(parentClassDesc, md);
+ }
+ }
+ }
+ // traverse to the parent!
+ return getHighestOverriddenMethod(parentClassDesc, curMethodDesc);
+ }
+ return curMethodDesc;
+ }
+
+ private void buildInheritanceTree() {
+
+ DFSInheritanceTreeCalculatingHighestOverriddenMethod(rootClassDescriptor);
+
+ }
+
+ private void addInheritanceConstraintsToHierarchyGraph() {
+
+ // DFS the inheritance tree and propagates nodes/edges of parent to child
+
+ // Node<ClassDescriptor> rootNode = inheritanceTree.getRootNode();
+ DFSInheritanceTree(rootClassDescriptor);
+
+ }
+
+ private void DFSInheritanceTree(ClassDescriptor parentClassDescriptor) {
+
+ // ClassDescriptor parentClassDescriptor = parentNode.getData();
+
+ Set<ClassDescriptor> children = getDirectSubClasses(parentClassDescriptor);
+ for (Iterator iterator = children.iterator(); iterator.hasNext();) {
+ ClassDescriptor childClassDescriptor = (ClassDescriptor) iterator.next();
+
+ HierarchyGraph parentGraph = getHierarchyGraph(parentClassDescriptor);
+ HierarchyGraph childGraph = getHierarchyGraph(childClassDescriptor);
+
+ // 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...
+ Set<HNode> parentNodeSet = parentGraph.getNodeSet();
+ 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);
+
+ // 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;
+ }
+