diff --git a/org.ntlab.traceAnalyzer/src/org/ntlab/deltaExtractor/DeltaExtractor.java b/org.ntlab.traceAnalyzer/src/org/ntlab/deltaExtractor/DeltaExtractor.java index 2f896fe..d7a16df 100644 --- a/org.ntlab.traceAnalyzer/src/org/ntlab/deltaExtractor/DeltaExtractor.java +++ b/org.ntlab.traceAnalyzer/src/org/ntlab/deltaExtractor/DeltaExtractor.java @@ -797,6 +797,7 @@ * @return ���o���� */ public ExtractedStructure extract(TracePoint creationTracePoint) { + creationTracePoint = creationTracePoint.duplicate(); Statement statement = creationTracePoint.getStatement(); if (statement instanceof FieldUpdate) { Reference targetRef = ((FieldUpdate)statement).getReference(); diff --git a/org.ntlab.traceAnalyzer/src/org/ntlab/trace/MethodExecution.java b/org.ntlab.traceAnalyzer/src/org/ntlab/trace/MethodExecution.java index 9c8e402..35d6479 100644 --- a/org.ntlab.traceAnalyzer/src/org/ntlab/trace/MethodExecution.java +++ b/org.ntlab.traceAnalyzer/src/org/ntlab/trace/MethodExecution.java @@ -108,6 +108,16 @@ } public long getExitTime() { + if (isTerminated || exitTime == 0L) { + TracePoint exitPoint = getExitPoint(); + if (!exitPoint.isValid()) return entryTime; + Statement lastStatament = exitPoint.getStatement(); + if (lastStatament instanceof MethodInvocation) { + return ((MethodInvocation) lastStatament).getCalledMethodExecution().getExitTime(); + } else { + return lastStatament.getTimeStamp(); + } + } return exitTime; } diff --git a/org.ntlab.traceAnalyzer/src/org/ntlab/trace/Trace.java b/org.ntlab.traceAnalyzer/src/org/ntlab/trace/Trace.java index 3319ee8..94f6113 100644 --- a/org.ntlab.traceAnalyzer/src/org/ntlab/trace/Trace.java +++ b/org.ntlab.traceAnalyzer/src/org/ntlab/trace/Trace.java @@ -466,12 +466,12 @@ } - private TracePoint getLastMethodEntryInThread(ArrayList rootExecutions) { + protected TracePoint getLastMethodEntryInThread(ArrayList rootExecutions) { MethodExecution lastExecution = rootExecutions.remove(rootExecutions.size() - 1); return getLastMethodEntryInThread(rootExecutions, lastExecution.getExitOutPoint()); } - private TracePoint getLastMethodEntryInThread(ArrayList rootExecutions, TracePoint start) { + protected TracePoint getLastMethodEntryInThread(ArrayList rootExecutions, TracePoint start) { return getLastMethodEntryInThread(rootExecutions, start, -1L); } @@ -482,11 +482,11 @@ * @param before * @return */ - private TracePoint getLastMethodEntryInThread(ArrayList rootExecutions, TracePoint start, final long before) { + protected TracePoint getLastMethodEntryInThread(ArrayList rootExecutions, TracePoint start, final long before) { final TracePoint cp[] = new TracePoint[1]; cp[0] = start; for (;;) { - if (!cp[0].isStepBackOut() && traverseMethodExecutionsInCallTreeBackward( + if (!cp[0].isStepBackOut() && traverseMethodExecutionsInCallTreeBackward ( new IMethodExecutionVisitor() { @Override public boolean preVisitThread(ThreadInstance thread) { return false; } @@ -511,6 +511,50 @@ } return null; } + + public boolean getLastStatementInThread(String threadId, final TracePoint[] start, final IStatementVisitor visitor) { + return getLastStatementInThread((ArrayList) threads.get(threadId).getRoot().clone(), start, start[0].getStatement().getTimeStamp(), visitor); + } + + protected boolean getLastStatementInThread(ArrayList rootExecutions, final TracePoint[] start, final long before, final IStatementVisitor visitor) { + final boolean[] bArrived = new boolean[] { + false + }; + for (;;) { + if (start[0].isValid() && traverseStatementsInCallTreeBackward( + new IStatementVisitor() { + @Override + public boolean preVisitStatement(Statement statement) { + if (statement instanceof MethodInvocation) { + MethodExecution methodExecution = ((MethodInvocation) statement).getCalledMethodExecution(); + if ((!methodExecution.isTerminated() && methodExecution.getExitTime() < before) || before == -1L) { + if (visitor.preVisitStatement(statement)) return true; + bArrived[0] = true; + return true; + } + } else { + if (statement.getTimeStamp() < before || before == -1L) { + if (visitor.preVisitStatement(statement)) return true; + bArrived[0] = true; + return true; + } + } + return visitor.preVisitStatement(statement); + } + @Override + public boolean postVisitStatement(Statement statement) { + return visitor.postVisitStatement(statement); + } + }, start[0])) { + return !bArrived[0]; + } + if (rootExecutions.size() == 0) break; + MethodExecution lastExecution = rootExecutions.remove(rootExecutions.size() - 1); + start[0] = lastExecution.getExitPoint(); + } + start[0] = null; + return false; + } public TracePoint getCreationTracePoint(final ObjectReference newObjectId, TracePoint before) { before = before.duplicate(); @@ -726,14 +770,12 @@ public MethodExecution traverseMethodEntriesInTraceBackward(IMethodExecutionVisitor visitor) { HashMap> threadRoots = new HashMap>(); HashMap threadLastPoints = new HashMap(); - Iterator threadsIterator = threads.keySet().iterator(); // �e�X���b�h�ɂ����Ĉ�ԍŌ�ɊJ�n�������\�b�h���s��T�� long traceLastTime = 0; String traceLastThread = null; long traceLastTime2 = 0; String traceLastThread2 = null; - for (; threadsIterator.hasNext();) { - String threadId = threadsIterator.next(); + for (String threadId: threads.keySet()) { ThreadInstance thread = threads.get(threadId); ArrayList rootExecutions = (ArrayList)thread.getRoot().clone(); threadRoots.put(threadId, rootExecutions); @@ -761,7 +803,6 @@ public MethodExecution traverseMethodEntriesInTraceBackward(IMethodExecutionVisitor visitor, TracePoint before) { HashMap> threadRoots = new HashMap>(); HashMap threadLastPoints = new HashMap(); - Iterator threadsIterator = threads.keySet().iterator(); String traceLastThread = null; long traceLastTime2 = 0; String traceLastThread2 = null; @@ -779,8 +820,7 @@ rootExecutions.remove(rootExecutions.size() - 1); } before = getLastMethodEntryInThread(rootExecutions, before); - for (; threadsIterator.hasNext();) { - String threadId = threadsIterator.next(); + for (String threadId: threads.keySet()) { ThreadInstance t = threads.get(threadId); if (t == thread) { threadRoots.put(threadId, rootExecutions); @@ -830,9 +870,7 @@ traceLastTime2 = 0; traceLastThread2 = null; boolean continueTraverse = false; - Iterator threadIterator = threadLastPoints.keySet().iterator(); - for (; threadIterator.hasNext();) { - String threadId = threadIterator.next(); + for (String threadId: threadLastPoints.keySet()) { if (!threadId.equals(traceLastThread)) { TracePoint lastTp = threadLastPoints.get(threadId); if (lastTp != null) { @@ -857,9 +895,8 @@ * @param markEnd �I������ */ public void traverseMarkedMethodExecutions(IMethodExecutionVisitor visitor, long markStart, long markEnd) { - Iterator threadsIterator = threads.keySet().iterator(); - for (; threadsIterator.hasNext();) { - ThreadInstance thread = threads.get(threadsIterator.next()); + for (String threadId: threads.keySet()) { + ThreadInstance thread = threads.get(threadId); thread.traverseMarkedMethodExecutions(visitor, markStart, markEnd); } } @@ -979,14 +1016,12 @@ public TracePoint traverseStatementsInTraceBackward(IStatementVisitor visitor) { HashMap> threadRoots = new HashMap>(); HashMap threadLastPoints = new HashMap(); - Iterator threadsIterator = threads.keySet().iterator(); // �e�X���b�h�ɂ����Ĉ�ԍŌ�ɊJ�n�������\�b�h���s��T�� long traceLastTime = 0; String traceLastThread = null; long traceLastTime2 = 0; String traceLastThread2 = null; - for (; threadsIterator.hasNext();) { - String threadId = threadsIterator.next(); + for (String threadId: threads.keySet()) { ThreadInstance thread = threads.get(threadId); ArrayList root = (ArrayList)thread.getRoot().clone(); threadRoots.put(threadId, root); @@ -1019,16 +1054,17 @@ * @return */ public TracePoint traverseStatementsInTraceBackward(IStatementVisitor visitor, TracePoint before) { + if (before == null) { + return traverseStatementsInTraceBackward(visitor); + } if (traverseStatamentsInCallTreeBackwardNoReturn(visitor, before)) return before; HashMap> threadRoots = new HashMap>(); HashMap threadLastPoints = new HashMap(); - Iterator threadsIterator = threads.keySet().iterator(); String traceLastThread = null; long traceLastTime2 = 0; String traceLastThread2 = null; ThreadInstance thread = threads.get(before.getStatement().getThreadNo()); - for (; threadsIterator.hasNext();) { - String threadId = threadsIterator.next(); + for (String threadId: threads.keySet()) { ThreadInstance t = threads.get(threadId); ArrayList rootExecutions = (ArrayList)t.getRoot().clone(); threadRoots.put(threadId, rootExecutions); @@ -1103,9 +1139,7 @@ traceLastTime2 = 0; traceLastThread2 = null; boolean continueTraverse = false; - Iterator threadsIterator = threadLastPoints.keySet().iterator(); - for (; threadsIterator.hasNext();) { - String threadId = threadsIterator.next(); + for (String threadId: threadLastPoints.keySet()) { if (!threadId.equals(traceLastThread)) { TracePoint threadLastTp = threadLastPoints.get(threadId); if (threadLastTp != null) { @@ -1132,14 +1166,17 @@ public boolean traverseStatementsInCallTreeBackward(IStatementVisitor visitor, TracePoint before) { for (;;) { if (traverseStatamentsInCallTreeBackwardNoReturn(visitor, before)) return true; - before.stepBackOver(); + while (!before.stepBackOver()) { + if (!before.isValid()) break; + if (visitor.postVisitStatement(before.getStatement())) return true; + } if (!before.isValid()) break; } return false; } /** - * before�ȍ~�̌Ăяo���؂��Ăяo���悩��̕��A�������ɍs����Ƃ���܂ŋt�����ɒT������ + * before�ȑO�̌Ăяo���؂��Ăяo���悩��̕��A�������ɍs����Ƃ���܂ŋt�����ɒT������ * * @param visitor ���s���̃r�W�^�[ * @param before �T���J�n���s���_ @@ -1190,6 +1227,7 @@ } public static String getDeclaringType(String methodSignature, boolean isConstructor) { + if (methodSignature == null) return null; if (isConstructor) { String[] fragments = methodSignature.split("\\("); return fragments[0].substring(fragments[0].lastIndexOf(' ') + 1); diff --git a/org.ntlab.traceAnalyzer/src/org/ntlab/trace/TraceJSON.java b/org.ntlab.traceAnalyzer/src/org/ntlab/trace/TraceJSON.java index ae900d2..80682c7 100644 --- a/org.ntlab.traceAnalyzer/src/org/ntlab/trace/TraceJSON.java +++ b/org.ntlab.traceAnalyzer/src/org/ntlab/trace/TraceJSON.java @@ -553,7 +553,7 @@ } @Override public boolean preVisitMethodExecution(MethodExecution methodExecution) { - if (methodExecution.getExitTime() < markStart) return true; // �T���I�� + if (!methodExecution.isTerminated() && methodExecution.getExitTime() < markStart) return true; // �T���I�� if (methodExecution.getEntryTime() > markEnd) return false; for (Statement s: methodExecution.getStatements()) { if (s instanceof BlockEnter) { @@ -639,7 +639,7 @@ } @Override public boolean preVisitMethodExecution(MethodExecution methodExecution) { - if (methodExecution.getExitTime() < markStart) return true; // �T���I�� + if (!methodExecution.isTerminated() && methodExecution.getExitTime() < markStart) return true; // �T���I�� if (methodExecution.getEntryTime() > markEnd) return false; int prevBlockId = -1; for (Statement s: methodExecution.getStatements()) { @@ -666,4 +666,262 @@ } return flows; } + + /** + * �g���[�X���̑S�X���b�h�𓯊������Ȃ���S���s�����t�����ɒT������ + * + * @param visitor ���s���̃r�W�^�[ + * @return ���f�����g���[�X�|�C���g + */ + public TracePoint traverseStatementsInTraceBackward(IStatementVisitor visitor) { + HashMap> threadRoots = new HashMap>(); + HashMap threadLastPoints = new HashMap(); + // �e�X���b�h�ɂ����Ĉ�ԍŌ�ɊJ�n�������\�b�h���s��T�� + long traceLastTime = 0; + String traceLastThread = null; + long traceLastTime2 = 0; + String traceLastThread2 = null; + for (String threadId: threads.keySet()) { + ThreadInstance thread = threads.get(threadId); + ArrayList roots = (ArrayList)thread.getRoot().clone(); + threadRoots.put(threadId, roots); + TracePoint threadLastTp; + do { + MethodExecution threadLastExecution = roots.remove(roots.size() - 1); + threadLastTp = threadLastExecution.getExitPoint(); + } while (!threadLastTp.isValid() && roots.size() > 0); + if (threadLastTp.isValid()) { + threadLastPoints.put(threadId, threadLastTp); + long threadLastTime; + if (threadLastTp.getStatement() instanceof MethodInvocation) { + threadLastTime = ((MethodInvocation) threadLastTp.getStatement()).getCalledMethodExecution().getExitTime(); + } else { + threadLastTime = threadLastTp.getStatement().getTimeStamp(); + } + if (traceLastTime < threadLastTime) { + traceLastTime2 = traceLastTime; + traceLastThread2 = traceLastThread; + traceLastTime = threadLastTime; + traceLastThread = threadId; + } + } else { + threadLastPoints.put(threadId, null); + } + } + return traverseStatementsInTraceBackwardSub(visitor, threadRoots, threadLastPoints, traceLastThread, traceLastThread2, traceLastTime2); + } + + /** + * �g���[�X���̑S�X���b�h�𓯊������Ȃ���w�肵���g���[�X�|�C���g����t�����ɒT������ + * + * @param visitor�@���s���̃r�W�^�[ + * @param before �T���J�n�g���[�X�|�C���g + * @return�@���f�����g���[�X�|�C���g + */ + public TracePoint traverseStatementsInTraceBackward(IStatementVisitor visitor, TracePoint before) { + if (before == null) { + return traverseStatementsInTraceBackward(visitor); + } + // �S�ẴX���b�h�̃g���[�X�|�C���g�� before �̑O�܂Ŋ����߂� + HashMap> threadRoots = new HashMap>(); + HashMap threadLastPoints = new HashMap(); + String traceLastThread = null; + long traceLastTime2 = 0; + String traceLastThread2 = null; + ThreadInstance thread = threads.get(before.getStatement().getThreadNo()); + for (String threadId: threads.keySet()) { + ThreadInstance t = threads.get(threadId); + ArrayList rootExecutions = (ArrayList)t.getRoot().clone(); + threadRoots.put(threadId, rootExecutions); + if (t == thread) { + traceLastThread = threadId; + threadLastPoints.put(threadId, before); + for (int n = rootExecutions.size() - 1; n >= 0; n--) { + MethodExecution root = rootExecutions.get(n); + if (root.getEntryTime() > before.getStatement().getTimeStamp()) { + rootExecutions.remove(n); + } else { + break; + } + } + if (rootExecutions.size() > 0) { + rootExecutions.remove(rootExecutions.size() - 1); + } + } else { + TracePoint threadBeforeTp; + do { + MethodExecution threadLastExecution = rootExecutions.remove(rootExecutions.size() - 1); + threadBeforeTp = threadLastExecution.getExitPoint(); + } while (!threadBeforeTp.isValid() && rootExecutions.size() > 0); + if (threadBeforeTp.isValid()) { + TracePoint[] tp = new TracePoint[] {threadBeforeTp}; + long threadLastTime; + if (before.getStatement() instanceof MethodInvocation) { + threadLastTime = ((MethodInvocation) before.getStatement()).getCalledMethodExecution().getExitTime(); + } else { + threadLastTime = before.getStatement().getTimeStamp(); + } + getLastStatementInThread(rootExecutions, tp, threadLastTime, new IStatementVisitor() { + @Override + public boolean preVisitStatement(Statement statement) { return false; } + @Override + public boolean postVisitStatement(Statement statement) { return false; } + }); + threadLastPoints.put(threadId, tp[0]); + if (tp[0] != null) { + if (tp[0].getStatement() instanceof MethodInvocation) { + threadLastTime = ((MethodInvocation) tp[0].getStatement()).getCalledMethodExecution().getExitTime(); // ��Exception �����������ꍇ�͍l���Ȃ��Ă悢? + } else { + threadLastTime = tp[0].getStatement().getTimeStamp(); + } + if (traceLastTime2 < threadLastTime) { + traceLastTime2 = threadLastTime; + traceLastThread2 = threadId; + } + } + } else { + threadLastPoints.put(threadId, null); + } + } + } + return traverseStatementsInTraceBackwardSub(visitor, threadRoots, threadLastPoints, traceLastThread, traceLastThread2, traceLastTime2); + } + + /** + * �g���[�X���̑S�X���b�h�𓯊������Ȃ���w�肵���g���[�X�|�C���g����t�����ɒT������ + * + * @param visitor�@���s���̃r�W�^�[ + * @param before �T���J�n���� + * @return�@���f�����g���[�X�|�C���g + */ + public TracePoint traverseStatementsInTraceBackward(IStatementVisitor visitor, long before) { + if (before <= 0L) { + return traverseStatementsInTraceBackward(visitor); + } + // �S�ẴX���b�h�̃g���[�X�|�C���g�� before �̑O�܂Ŋ����߂� + HashMap> threadRoots = new HashMap>(); + HashMap threadLastPoints = new HashMap(); + long traceLastTime = 0; + String traceLastThread = null; + long traceLastTime2 = 0; + String traceLastThread2 = null; + for (String threadId: threads.keySet()) { + ThreadInstance t = threads.get(threadId); + ArrayList rootExecutions = (ArrayList)t.getRoot().clone(); + threadRoots.put(threadId, rootExecutions); + TracePoint threadBeforeTp; + do { + MethodExecution threadLastExecution = rootExecutions.remove(rootExecutions.size() - 1); + threadBeforeTp = threadLastExecution.getExitPoint(); + } while (!threadBeforeTp.isValid() && rootExecutions.size() > 0); + if (threadBeforeTp.isValid()) { + TracePoint[] tp = new TracePoint[] {threadBeforeTp}; + getLastStatementInThread(rootExecutions, tp, before, new IStatementVisitor() { + @Override + public boolean preVisitStatement(Statement statement) { return false; } + @Override + public boolean postVisitStatement(Statement statement) { return false; } + }); + threadLastPoints.put(threadId, tp[0]); + if (tp[0] != null) { + long threadLastTime; + if (tp[0].getStatement() instanceof MethodInvocation) { + threadLastTime = ((MethodInvocation) tp[0].getStatement()).getCalledMethodExecution().getExitTime(); // ��Exception �����������ꍇ�͍l���Ȃ��Ă悢? + } else { + threadLastTime = tp[0].getStatement().getTimeStamp(); + } + if (traceLastTime < threadLastTime) { + traceLastTime2 = traceLastTime; + traceLastThread2 = traceLastThread; + traceLastTime = threadLastTime; + traceLastThread = threadId; + } + } + } else { + threadLastPoints.put(threadId, null); + } + } + return traverseStatementsInTraceBackwardSub(visitor, threadRoots, threadLastPoints, traceLastThread, traceLastThread2, traceLastTime2); + } + + private TracePoint traverseStatementsInTraceBackwardSub(IStatementVisitor visitor, + HashMap> threadRoots, + HashMap threadLastPoints, + String traceLastThread, String traceLastThread2, long traceLastTime2) { + // �S�X���b�h�̓������Ƃ�Ȃ���t�����Ɏ��s����T������ + for (;;) { + // �T���Ώۂ̃X���b�h���̋t�����T�� + TracePoint lastTp = threadLastPoints.get(traceLastThread); + while (lastTp != null) { + Statement statement = lastTp.getStatement(); + if (visitor.preVisitStatement(statement)) return lastTp; + if (statement instanceof MethodInvocation) { + // �Ăяo���悪����ꍇ�A�Ăяo����ɐ��� + lastTp.stepBackNoReturn(); + if (lastTp.isValid()) { + // ���ʂɌĂяo����Ɉڂ����ꍇ + MethodExecution methodExecution = ((MethodInvocation) statement).getCalledMethodExecution(); + if (!methodExecution.isTerminated() && methodExecution.getExitTime() < traceLastTime2) { + break; + } + continue; + } + // ��̃��\�b�h���s�̏ꍇ + } else { + if (visitor.postVisitStatement(statement)) return lastTp; + } + if (lastTp.isValid() && lastTp.getStatement().getTimeStamp() < traceLastTime2) break; + // 1�X�e�b�v�����߂� + while (!lastTp.stepBackOver() && lastTp.isValid()) { + // �Ăяo�����ɖ߂����ꍇ(���\�b�h�Ăяo�����ɕ��A) + statement = lastTp.getStatement(); + if (visitor.postVisitStatement(statement)) return lastTp; + } + if (!lastTp.isValid()) { + // �Ăяo���؂̊J�n���_�܂ŒT�����I�����ꍇ + ArrayList roots = threadRoots.get(traceLastThread); + while (!lastTp.isValid() && roots.size() > 0) { + // ���̌Ăяo���؂�T�� + MethodExecution lastExecution = roots.remove(roots.size() - 1); + lastTp = lastExecution.getExitPoint(); + } + if (lastTp.isValid()) { + // ���̌Ăяo���؂�����΂�����Ōォ��T�� + threadLastPoints.put(traceLastThread, lastTp); + if (lastTp.getStatement().getTimeStamp() < traceLastTime2) break; + } else { + // ���̃X���b�h�̒T�������ׂďI�������ꍇ + threadLastPoints.put(traceLastThread, null); + break; + } + } + } + traceLastThread = traceLastThread2; + // ���̎��ɒT�����ׂ��X���b�h(���T���̗̈悪��ԍŌ�܂Ŏc���Ă���X���b�h)�����肷�� + traceLastTime2 = 0; + traceLastThread2 = null; + boolean continueTraverse = false; + for (String threadId: threadLastPoints.keySet()) { + if (!threadId.equals(traceLastThread)) { + TracePoint threadLastTp = threadLastPoints.get(threadId); + if (threadLastTp != null) { + continueTraverse = true; + long threadLastTime; + if (threadLastTp.getStatement() instanceof MethodInvocation) { + threadLastTime = ((MethodInvocation) threadLastTp.getStatement()).getCalledMethodExecution().getExitTime(); + } else { + threadLastTime = threadLastTp.getStatement().getTimeStamp(); + } + if (traceLastTime2 < threadLastTime) { + traceLastTime2 = threadLastTime; + traceLastThread2 = threadId; + } + } + } + } + if (traceLastThread == null && traceLastThread2 == null) break; + if (!continueTraverse && threadLastPoints.get(traceLastThread) == null) break; + } + return null; + } } \ No newline at end of file