diff --git a/src/org/ntlab/deltaExtractor/DeltaExtractor.java b/src/org/ntlab/deltaExtractor/DeltaExtractor.java index 36291dd..794b9a4 100644 --- a/src/org/ntlab/deltaExtractor/DeltaExtractor.java +++ b/src/org/ntlab/deltaExtractor/DeltaExtractor.java @@ -336,6 +336,15 @@ } else { aliasCollector.addAlias(new DeltaAlias(Alias.AliasType.RECEIVER, 0, objList.get(retIndex), tracePoint.duplicate(), false)); } + } else if (objList.get(retIndex) == null) { + // static �Ăяo���������ꍇ + removeList.add(thisObjectId); // ��ň�U�AthisObject ����菜�� + isTrackingThis = true; // �Ăяo�����T���O�ɕ��� + if (isSrcSide) { + aliasCollector.addAlias(new DeltaAlias(Alias.AliasType.THIS, 0, thisObjectId, tracePoint.duplicate(), true)); + } else { + aliasCollector.addAlias(new DeltaAlias(Alias.AliasType.THIS, 0, thisObjectId, tracePoint.duplicate(), false)); + } } if (isLost) { checkList.add(objList.get(retIndex)); diff --git a/src/org/ntlab/deltaExtractor/DeltaExtractorJSON.java b/src/org/ntlab/deltaExtractor/DeltaExtractorJSON.java index 4332284..6837abf 100644 --- a/src/org/ntlab/deltaExtractor/DeltaExtractorJSON.java +++ b/src/org/ntlab/deltaExtractor/DeltaExtractorJSON.java @@ -247,6 +247,11 @@ isTrackingThis = true; // �Ăяo�����T���O�ɕ��� } aliasCollector.addAlias(new Alias(Alias.AliasType.RECEIVER, 0, objList.get(retIndex), tracePoint.duplicate())); + } else if (objList.get(retIndex) == null) { + // static �Ăяo���������ꍇ + removeList.add(thisObjectId); // ��ň�U�AthisObject ����菜�� + isTrackingThis = true; // �Ăяo�����T���O�ɕ��� + aliasCollector.addAlias(new Alias(Alias.AliasType.THIS, 0, thisObjectId, tracePoint.duplicate())); } if (isLost) { checkList.add(objList.get(retIndex)); diff --git a/src/org/ntlab/deltaViewer/CollaborationLayout.java b/src/org/ntlab/deltaViewer/CollaborationLayout.java index bf3aad3..30f331b 100644 --- a/src/org/ntlab/deltaViewer/CollaborationLayout.java +++ b/src/org/ntlab/deltaViewer/CollaborationLayout.java @@ -83,7 +83,7 @@ } // Extract the reference access history. - List references = objectCallGraph.getReferences(); + List references = new ArrayList<>(objectCallGraph.getReferences()); Map> referenceHistory = new HashMap<>(); int order = 0; for (Alias a: aliasCollector.getAliasList()) { @@ -106,13 +106,16 @@ } else if (a.getAliasType() == AliasType.RETURN_VALUE) { MethodExecution methodExec = a.getMethodExecution(); if (methodExec.getSignature().contains("List.get(") || - methodExec.getSignature().contains("Map.get(")) { + methodExec.getSignature().contains("Map.get(") || + methodExec.getSignature().contains(".next()") || + methodExec.getSignature().contains(".iterator()") || + methodExec.getSignature().contains(".listIterator()")) { String srcObjId = methodExec.getThisObjId(); String dstObjId = methodExec.getReturnValue().getId(); String srcClassName = methodExec.getThisClassName(); String dstClassName = methodExec.getReturnValue().getActualType(); idx = references.indexOf(new Reference(srcObjId, dstObjId, srcClassName, dstClassName)); - } + } } else if (a.getAliasType() == AliasType.CONSTRACTOR_INVOCATION) { MethodInvocation c = (MethodInvocation) a.getOccurrencePoint().getStatement(); String srcObjId = a.getMethodExecution().getThisObjId(); @@ -125,6 +128,29 @@ String srcObjId = a.getMethodExecution().getThisObjId(); String srcClassName = a.getMethodExecution().getThisClassName(); idx = references.indexOf(new Reference(srcObjId, ac.getArrayObjectId(), srcClassName, ac.getArrayClassName())); + } else if (a.getAliasType() == AliasType.THIS) { + Statement st = a.getOccurrencePoint().getStatement(); + if (st instanceof MethodInvocation) { + MethodExecution methodExec = ((MethodInvocation) st).getCalledMethodExecution(); + if (methodExec.isStatic()) { + // For calls to a static method. + String dstClassName = methodExec.getThisClassName(); + String srcClassName = methodExec.getCallerMethodExecution().getThisClassName(); + String dstObjId = methodExec.getThisObjId() + ":" + dstClassName; + String srcObjId = null; + if (!a.getMethodExecution().isStatic()) { + srcObjId = methodExec.getCallerMethodExecution().getThisObjId(); + } else { + srcObjId = methodExec.getCallerMethodExecution().getThisObjId() + ":" + srcClassName; + } + Reference r = new Reference(srcObjId, dstObjId, srcClassName, dstClassName); + idx = references.indexOf(r); + if (idx < 0) { + references.add(r); + idx = references.indexOf(r); + } + } + } } if (idx >= 0) { Reference r = references.get(idx); diff --git a/src/org/ntlab/deltaViewer/CollaborationObjectCallGraph.java b/src/org/ntlab/deltaViewer/CollaborationObjectCallGraph.java index fff5242..6f3a808 100644 --- a/src/org/ntlab/deltaViewer/CollaborationObjectCallGraph.java +++ b/src/org/ntlab/deltaViewer/CollaborationObjectCallGraph.java @@ -7,11 +7,14 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; import java.util.stream.Collectors; import org.ntlab.deltaExtractor.ExtractedStructure; import org.ntlab.trace.MethodExecution; import org.ntlab.trace.MethodInvocation; +import org.ntlab.trace.ObjectReference; import org.ntlab.trace.Reference; import org.ntlab.trace.Statement; import org.ntlab.trace.TracePoint; @@ -25,12 +28,14 @@ private Set references = new HashSet<>(); private List startPoints = new ArrayList<>(); // Common ancestor point private List relatedPoints = new ArrayList<>(); + private SortedSet timeStamps = new TreeSet<>(); // List of time stamps of related points public CollaborationObjectCallGraph(ExtractedStructure e) { references.addAll(e.getDelta().getSrcSide()); references.addAll(e.getDelta().getDstSide()); startPoints.add(e.getCoordinator()); relatedPoints.add(e.getRelatedTracePoint().duplicate()); + timeStamps.add(getTimeStampOfRelatedPoint(e.getRelatedTracePoint(), e)); } @Override @@ -53,6 +58,11 @@ return null; } + @Override + public SortedSet getTimeStamps() { + return timeStamps; + } + /** * Merge ExtractedStructure not to overlap reference. * @@ -117,10 +127,12 @@ startPoints.clear(); startPoints.add(lca); - // Is it in time stamp order? TracePoint otherRelatedTp = e.getRelatedTracePoint().duplicate(); - relatedPoints.add(otherRelatedTp); - relatedPoints = sortTracePointByTimeStamp(relatedPoints); + long rpTimeStamp = getTimeStampOfRelatedPoint(otherRelatedTp, e); + int idx = timeStamps.headSet(rpTimeStamp).size(); + relatedPoints.add(idx, otherRelatedTp); + timeStamps.add(rpTimeStamp); +// relatedPoints = sortTracePointByTimeStamp(relatedPoints); } /** @@ -147,6 +159,23 @@ } return qTmp; } + + private Long getTimeStampOfRelatedPoint(TracePoint relatedTracePoint, ExtractedStructure e) { + ObjectReference targetObj = null; + if (e.getDelta().getDstSide().size() > 0) { + targetObj = e.getDelta().getDstSide().get(0).getDstObject(); + } else { + targetObj = new ObjectReference(e.getCoordinator().getThisObjId(), e.getCoordinator().getThisClassName()); + } + if (relatedTracePoint.isMethodEntry() && relatedTracePoint.getMethodExecution().getArguments().contains(targetObj)) { + return relatedTracePoint.getMethodExecution().getEntryTime(); + } + if (relatedTracePoint.getStatement() instanceof MethodInvocation) { + return ((MethodInvocation) relatedTracePoint.getStatement()).getCalledMethodExecution().getExitTime(); + } else { + return relatedTracePoint.getStatement().getTimeStamp(); + } + } /** * Sort TracePoint in time stamp order. diff --git a/src/org/ntlab/deltaViewer/CollaborationViewer.java b/src/org/ntlab/deltaViewer/CollaborationViewer.java index 9b9ef31..10fc087 100644 --- a/src/org/ntlab/deltaViewer/CollaborationViewer.java +++ b/src/org/ntlab/deltaViewer/CollaborationViewer.java @@ -48,7 +48,7 @@ public void init(IObjectCallGraph objectCallGraph, IAliasCollector aliasCollector, IObjectLayout layout) { this.objectCallGraph = objectCallGraph; this.aliasCollector = aliasCollector; - createObjectVertices(this.objectCallGraph); + createObjectVertices(this.objectCallGraph, aliasCollector); layout.execute(objectCallGraph, aliasCollector, objectToVertexMap); createEdgeToObject(this.objectCallGraph, this.aliasCollector); } @@ -99,12 +99,15 @@ if (numFrameAlias != null) { if (curFrameAlias != null) { - for (TracePoint rp: relatedPoints) { - if (curFrameAlias.getTimeStamp() < rp.getStatement().getTimeStamp() && rp.getStatement().getTimeStamp() < numFrameAlias.getTimeStamp()) { + int i = 0; + for (Long rpTime:objectCallGraph.getTimeStamps()) { + if (curFrameAlias.getTimeStamp() <= rpTime && rpTime < numFrameAlias.getTimeStamp()) { System.out.println("\r\n" + TAG + ": Last Animation."); + TracePoint rp = relatedPoints.get(i); doLastAnimation(numFrame, rp); return; } + i++; } } doAnimation(curFrame, numFrame); @@ -345,8 +348,9 @@ * Create vertices(mxGraph) and OvjectVerticies in {@code objectToVertexMap}. Vertices(mxGraph) coordinate are appropriate. * * @param objectCallGraph + * @param aliasCollector */ - private void createObjectVertices(IObjectCallGraph objectCallGraph) { + private void createObjectVertices(IObjectCallGraph objectCallGraph, IAliasCollector aliasCollector) { //Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology. mxgraph.getModel().beginUpdate(); try { @@ -408,6 +412,17 @@ } } } + for (Alias alias: aliasCollector.getAliasList()) { + if (alias.getAliasType() == Alias.AliasType.THIS) { + if (!objectToVertexMap.containsKey(alias.getObjectId())) { + // When both of the calling and called method are static. + String thisObjId = alias.getObjectId(); + String thisClassName = alias.getMethodExecution().getThisClassName(); + mxICell vertex = (mxICell) mxgraph.insertDeltaVertex(getMxDefaultParent(), thisObjId, thisClassName, 0, 0, objecVertexWidth, ObjectVertexHeight, "fillColor=white"); //creates a white vertex. + objectToVertexMap.put(thisObjId, new ObjectVertex(thisClassName, vertex, 0, 0)); + } + } + } } finally { mxgraph.getModel().endUpdate(); } @@ -468,6 +483,10 @@ srcClassName = nextMethodExec.getThisClassName(); fieldName = ""; System.out.println(TAG + ": Create Map of Edge.(ClassName=" + srcClassName + ")"); + } else if (nextMethodExec.getSignature().contains(".next()") || nextMethodExec.getSignature().contains(".iterator()") || nextMethodExec.getSignature().contains(".listIterator()")) { + srcClassName = nextMethodExec.getThisClassName(); + fieldName = ""; + System.out.println(TAG + ": Create List Iterator of Edge.(ClassName=" + srcClassName + ")"); } } else { if (nextAlias.getAliasType() == AliasType.FIELD) { // When final local. diff --git a/src/org/ntlab/deltaViewer/DeltaObjectCallGraph.java b/src/org/ntlab/deltaViewer/DeltaObjectCallGraph.java index b90d9f2..2983e6c 100644 --- a/src/org/ntlab/deltaViewer/DeltaObjectCallGraph.java +++ b/src/org/ntlab/deltaViewer/DeltaObjectCallGraph.java @@ -3,9 +3,13 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.SortedSet; +import java.util.TreeSet; import org.ntlab.deltaExtractor.ExtractedStructure; import org.ntlab.trace.MethodExecution; +import org.ntlab.trace.MethodInvocation; +import org.ntlab.trace.ObjectReference; import org.ntlab.trace.Reference; import org.ntlab.trace.TracePoint; @@ -13,12 +17,14 @@ private List references = new ArrayList<>(); private List startPoints = new ArrayList<>(); private List relatedPoints = new ArrayList<>(); + private SortedSet timeStamps = new TreeSet<>(); // List of time stamps of related points public DeltaObjectCallGraph(ExtractedStructure e) { references.addAll(e.getDelta().getSrcSide()); references.addAll(e.getDelta().getDstSide()); startPoints.add(e.getCoordinator()); relatedPoints.add(e.getRelatedTracePoint()); + timeStamps.add(getTimeStampOfRelatedPoint(e.getRelatedTracePoint(), e)); } @Override @@ -42,4 +48,26 @@ // TODO Auto-generated method stub return null; } + + @Override + public SortedSet getTimeStamps() { + return timeStamps; + } + + private Long getTimeStampOfRelatedPoint(TracePoint relatedTracePoint, ExtractedStructure e) { + ObjectReference targetObj = null; + if (e.getDelta().getDstSide().size() > 0) { + targetObj = e.getDelta().getDstSide().get(0).getDstObject(); + } else { + targetObj = new ObjectReference(e.getCoordinator().getThisObjId(), e.getCoordinator().getThisClassName()); + } + if (relatedTracePoint.isMethodEntry() && relatedTracePoint.getMethodExecution().getArguments().contains(targetObj)) { + return relatedTracePoint.getMethodExecution().getEntryTime(); + } + if (relatedTracePoint.getStatement() instanceof MethodInvocation) { + return ((MethodInvocation) relatedTracePoint.getStatement()).getCalledMethodExecution().getExitTime(); + } else { + return relatedTracePoint.getStatement().getTimeStamp(); + } + } } diff --git a/src/org/ntlab/deltaViewer/DeltaViewer.java b/src/org/ntlab/deltaViewer/DeltaViewer.java index 2294bb9..7a96622 100644 --- a/src/org/ntlab/deltaViewer/DeltaViewer.java +++ b/src/org/ntlab/deltaViewer/DeltaViewer.java @@ -549,10 +549,17 @@ MethodExecution nextMethodExec = nextAlias.getMethodExecution(); //Array��List�̂Ƃ��������x����t����i�m���ɕ������Ă�����̂Ƃ�)getSignature->contains("List.get(") || "Map.get(") <�z���C�g���X�g> if (nextMethodExec.getSignature().contains("List.get(") || - nextMethodExec.getSignature().contains("Map.get(")) { + nextMethodExec.getSignature().contains("Map.get(") || + nextMethodExec.getSignature().contains(".next()") || + nextMethodExec.getSignature().contains(".iterator()") || + nextMethodExec.getSignature().contains(".listIterator()")) { srcClassName = nextMethodExec.getThisClassName(); - fieldName = nextMethodExec.getArguments().get(0).getId(); - System.out.println("rTHIS " + srcClassName + ", " + nextMethodExec.getArguments().get(0).getId()); + if (nextMethodExec.getArguments().size() > 0) { + fieldName = nextMethodExec.getArguments().get(0).getId(); + } else { + fieldName = ""; + } + System.out.println("rTHIS " + srcClassName + ", " + fieldName); } } else { Statement statement = nextAlias.getOccurrencePoint().getStatement(); diff --git a/src/org/ntlab/deltaViewer/ForwardAliasCollector.java b/src/org/ntlab/deltaViewer/ForwardAliasCollector.java index 93ca42f..8782053 100644 --- a/src/org/ntlab/deltaViewer/ForwardAliasCollector.java +++ b/src/org/ntlab/deltaViewer/ForwardAliasCollector.java @@ -3,6 +3,8 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.SortedSet; +import java.util.TreeSet; import org.ntlab.deltaExtractor.Alias; import org.ntlab.deltaExtractor.Alias.AliasType; @@ -138,7 +140,10 @@ addAlias(methodInvAlias); } if (methodSignature.contains("List.get(") || - methodSignature.contains("Map.get(")) { + methodSignature.contains("Map.get(") || + methodSignature.contains(".next()") || + methodSignature.contains(".iterator()") || + methodSignature.contains(".listIterator()")) { String returnClass = mi.getCalledMethodExecution().getReturnValue().getActualType(); Reference ref = new Reference(mi.getCalledMethodExecution().getThisObjId(), returnValue, mi.getCalledMethodExecution().getThisClassName(), returnClass); ref.setCollection(true); @@ -185,6 +190,7 @@ private List references = new ArrayList<>(); private List startPoints = new ArrayList<>(); private List relatedPoints = new ArrayList<>(); + private SortedSet timeStamps = new TreeSet<>(); // List of time stamps of related points public void addReference(Reference r) { if (!references.contains(r)) references.add(r); @@ -196,6 +202,7 @@ public void addRelatedPoint(TracePoint tp) { relatedPoints.add(tp); + timeStamps.add(tp.getStatement().getTimeStamp()); // Will not work when a formal parameter is passed and related to this object. } @Override @@ -217,6 +224,11 @@ public Map> getCallTree() { return null; } + + @Override + public SortedSet getTimeStamps() { + return null; + } } } diff --git a/src/org/ntlab/deltaViewer/ForwardLayout.java b/src/org/ntlab/deltaViewer/ForwardLayout.java index 893535f..021fb0c 100644 --- a/src/org/ntlab/deltaViewer/ForwardLayout.java +++ b/src/org/ntlab/deltaViewer/ForwardLayout.java @@ -51,7 +51,10 @@ } else if (a.getAliasType() == AliasType.RETURN_VALUE) { MethodExecution methodExec = a.getMethodExecution(); if (methodExec.getSignature().contains("List.get(") || - methodExec.getSignature().contains("Map.get(")) { + methodExec.getSignature().contains("Map.get(") || + methodExec.getSignature().contains(".next()") || + methodExec.getSignature().contains(".iterator()") || + methodExec.getSignature().contains(".listIterator()")) { String srcObjId = methodExec.getThisObjId(); String dstObjId = methodExec.getReturnValue().getId(); String srcClassName = methodExec.getThisClassName(); diff --git a/src/org/ntlab/deltaViewer/IObjectCallGraph.java b/src/org/ntlab/deltaViewer/IObjectCallGraph.java index 91d7be5..8073ab5 100644 --- a/src/org/ntlab/deltaViewer/IObjectCallGraph.java +++ b/src/org/ntlab/deltaViewer/IObjectCallGraph.java @@ -2,6 +2,7 @@ import java.util.List; import java.util.Map; +import java.util.SortedSet; import org.ntlab.trace.MethodExecution; import org.ntlab.trace.Reference; @@ -17,6 +18,8 @@ List getStartPoints(); List getRelatedPoints(); + + SortedSet getTimeStamps(); Map> getCallTree(); } diff --git a/src/org/ntlab/deltaViewer/MagnetRONViewer.java b/src/org/ntlab/deltaViewer/MagnetRONViewer.java index e46c165..c05b330 100644 --- a/src/org/ntlab/deltaViewer/MagnetRONViewer.java +++ b/src/org/ntlab/deltaViewer/MagnetRONViewer.java @@ -36,6 +36,7 @@ import org.ntlab.trace.ObjectReference; import org.ntlab.trace.Reference; import org.ntlab.trace.Statement; +import org.ntlab.trace.Trace; import org.ntlab.trace.TracePoint; import com.mxgraph.canvas.mxGraphics2DCanvas; @@ -233,6 +234,9 @@ ObjectVertex objectVertex = objectToVertexMap.get(alias.getObjectId()); MethodExecution methodExec = alias.getMethodExecution(); String srcObjId = alias.getMethodExecution().getThisObjId(); + if (Trace.isNull(srcObjId)) { + srcObjId += ":" + alias.getMethodExecution().getThisClassName(); + } mxICell srcCell = (mxICell)objectToVertexMap.get(srcObjId).getCell(); double srcWidth = srcCell.getGeometry().getWidth(); double srcHeight = srcCell.getGeometry().getHeight(); @@ -878,8 +882,12 @@ methodSignature = formatMethodSignature(methodSignature, methodExecution.getThisClassName()); } + //�@Why is the following code needed? if (methodExecution.isStatic() && !objectId.equals("0")) { objectId = methodExecution.getCallerMethodExecution().getThisObjId(); + if (objectId.matches("0")) { + objectId += ":" + methodExecution.getCallerMethodExecution().getThisClassName(); + } } mxICell parentCell = (mxICell) objectToVertexMap.get(objectId).getCell(); @@ -1196,7 +1204,12 @@ if (!calledMethodExecution.isStatic()) { objectToVertexMap.get(calledMethodExecution.getThisObjId()).getVertexMethodExecutions().remove(methodExecToVertexMap.get(calledMethodExecution)); } else { - objectToVertexMap.get(calledMethodExecution.getCallerMethodExecution().getThisObjId()).getVertexMethodExecutions().remove(methodExecToVertexMap.get(calledMethodExecution)); + // Why is this object id of the caller method used? + String objId = calledMethodExecution.getCallerMethodExecution().getThisObjId(); + if (objId.matches("0")) { + objId += ":" + calledMethodExecution.getCallerMethodExecution().getThisClassName(); + } + objectToVertexMap.get(objId).getVertexMethodExecutions().remove(methodExecToVertexMap.get(calledMethodExecution)); } methodExecToVertexMap.get(calledMethodExecution).getLocals().remove(sourceObjectVertex); methodExecToVertexMap.remove(calledMethodExecution);