diff --git a/org.ntlab.traceAnalyzer/src/org/ntlab/trace/Trace.java b/org.ntlab.traceAnalyzer/src/org/ntlab/trace/Trace.java index ae2e659..3319ee8 100644 --- a/org.ntlab.traceAnalyzer/src/org/ntlab/trace/Trace.java +++ b/org.ntlab.traceAnalyzer/src/org/ntlab/trace/Trace.java @@ -44,13 +44,6 @@ e.printStackTrace(); } } - - public static Trace getInstance() { - if (theTrace == null) { - theTrace = new Trace(); - } - return theTrace; - } private void read(BufferedReader file) throws IOException { // �g���[�X�t�@�C���ǂݍ��� @@ -172,11 +165,23 @@ } /** - * �S�X���b�h���擾���� - * @return �X���b�hID����X���b�h�C���X�^���X�ւ̃}�b�v + * �I�����C����͗p�V���O���g���̎擾 + * @return �I�����C����͗p�g���[�X */ - public HashMap getAllThreads() { - return threads; + public static Trace getInstance() { + if (theTrace == null) { + theTrace = new Trace(); + } + return theTrace; + } + + /** + * �X���b�hID���w�肵�ăX���b�h�C���X�^���X���擾����(�I�����C����͗p) + * @param threadId + * @return �X���b�h�C���X�^���X + */ + public static ThreadInstance getThreadInstance(String threadId) { + return getInstance().threads.get(threadId); } /** @@ -198,215 +203,13 @@ ThreadInstance t = getInstance().threads.get(String.valueOf(thread.getId())); return t.getCurrentTracePoint(); } - - /** - * methodSignature �ɑO����v���郁�\�b�h�������ƒ��\�b�h�̍Ō�̎��s - * @param methodSignature ���\�b�h��(�O����v�Ō�������) - * @return �Y������Ō�̃��\�b�h���s - */ - public MethodExecution getLastMethodExecution(final String methodSignature) { - return traverseMethodEntriesInTraceBackward(new IMethodExecutionVisitor() { - @Override - public boolean preVisitThread(ThreadInstance thread) { return false; } - @Override - public boolean postVisitThread(ThreadInstance thread) { return false; } - @Override - public boolean preVisitMethodExecution(MethodExecution methodExecution) { return false; } - @Override - public boolean postVisitMethodExecution(MethodExecution methodExecution, ArrayList children) { - if (methodExecution.getSignature().startsWith(methodSignature)) return true; - return false; - } - }); - } /** - * �g���[�X���̑S���\�b�h���s�̊J�n�n�_���t�����ɒT������ - * @param visitor ���\�b�h���s�̃r�W�^�[(postVisitMethodExecution()�����ĂѕԂ��Ȃ��̂Œ���) - * @return ���f�������\�b�h���s + * �S�X���b�h���擾���� + * @return �X���b�hID����X���b�h�C���X�^���X�ւ̃}�b�v */ - 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(); - ThreadInstance thread = threads.get(threadId); - ArrayList rootExecutions = (ArrayList)thread.getRoot().clone(); - threadRoots.put(threadId, rootExecutions); - TracePoint threadLastTp = getLastMethodEntryInThread(rootExecutions); - threadLastPoints.put(threadId, threadLastTp); - if (threadLastTp != null) { - long threadLastTime = threadLastTp.getMethodExecution().getEntryTime(); - if (traceLastTime < threadLastTime) { - traceLastTime2 = traceLastTime; - traceLastThread2 = traceLastThread; - traceLastTime = threadLastTime; - traceLastThread = threadId; - } - } - } - return traverseMethodEntriesInTraceBackwardSub(visitor, threadRoots, threadLastPoints, traceLastThread, traceLastThread2, traceLastTime2); - } - - /** - * methodSignature �ɑO����v���郁�\�b�h�������ƒ��\�b�h�� before �ȑO�̍Ō�̎��s - * @param methodSignature ���\�b�h��(�O����v�Ō�������) - * @param before�@�T���J�n�g���[�X�|�C���g(������ȑO��T��) - * @return�@�Y������Ō�̃��\�b�h���s - */ - public MethodExecution getLastMethodExecution(final String methodSignature, TracePoint before) { - return traverseMethodEntriesInTraceBackward(new IMethodExecutionVisitor() { - @Override - public boolean preVisitThread(ThreadInstance thread) { return false; } - @Override - public boolean postVisitThread(ThreadInstance thread) { return false; } - @Override - public boolean preVisitMethodExecution(MethodExecution methodExecution) { return false; } - @Override - public boolean postVisitMethodExecution(MethodExecution methodExecution, ArrayList children) { - if (methodExecution.getSignature().startsWith(methodSignature)) return true; - return false; - } - }, before); - } - - /** - * �w�肵�����s���_�ȑO�Ɏ��s���J�n���ꂽ���\�b�h���s�̊J�n���_���t�����ɒT������ - * @param visitor ���\�b�h���s�̃r�W�^�[(postVisitMethodExecution()�����ĂѕԂ��Ȃ��̂Œ���) - * @param before �T���J�n���_ - * @return ���f�������\�b�h���s - */ - 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; - ThreadInstance thread = threads.get(before.getStatement().getThreadNo()); - ArrayList rootExecutions = (ArrayList)thread.getRoot().clone(); - for (int n = rootExecutions.size() - 1; n >= 0; n--) { - MethodExecution root = rootExecutions.get(n); - if (root.getEntryTime() > before.getMethodExecution().getEntryTime()) { - rootExecutions.remove(n); - } else { - break; - } - } - if (rootExecutions.size() > 0) { - rootExecutions.remove(rootExecutions.size() - 1); - } - before = getLastMethodEntryInThread(rootExecutions, before); - for (; threadsIterator.hasNext();) { - String threadId = threadsIterator.next(); - ThreadInstance t = threads.get(threadId); - if (t == thread) { - threadRoots.put(threadId, rootExecutions); - traceLastThread = threadId; - threadLastPoints.put(threadId, before); - } else { - ArrayList rootExes = (ArrayList)t.getRoot().clone(); - threadRoots.put(threadId, rootExes); - MethodExecution threadLastExecution = rootExes.remove(rootExes.size() - 1); - TracePoint threadBeforeTp = getLastMethodEntryInThread(rootExes, threadLastExecution.getExitOutPoint(), before.getMethodExecution().getEntryTime()); - threadLastPoints.put(threadId, threadBeforeTp); - if (threadBeforeTp != null) { - long threadLastTime = threadBeforeTp.getMethodExecution().getEntryTime(); - if (traceLastTime2 < threadLastTime) { - traceLastTime2 = threadLastTime; - traceLastThread2 = threadId; - } - } - } - } - return traverseMethodEntriesInTraceBackwardSub(visitor, threadRoots, threadLastPoints, traceLastThread, traceLastThread2, traceLastTime2); - } - - private MethodExecution traverseMethodEntriesInTraceBackwardSub( - final IMethodExecutionVisitor visitor, - HashMap> threadRoots, HashMap threadLastPoints, - String traceLastThread, String traceLastThread2, long traceLastTime2) { - // �S�X���b�h�̓������Ƃ�Ȃ���t�����Ƀ��\�b�h���s��T������ - for (;;) { - // �T���Ώۂ̃X���b�h���̋t�����T�� - TracePoint threadLastTp = threadLastPoints.get(traceLastThread); - MethodExecution threadLastExecution = threadLastTp.getMethodExecution(); - do { - threadLastTp.stepBackOver(); - // ���̃X���b�h�̎��̃��\�b�h���s�J�n���_�܂ŒT������ - threadLastTp = getLastMethodEntryInThread(threadRoots.get(traceLastThread), threadLastTp); - if (threadLastTp == null) break; - if (visitor.postVisitMethodExecution(threadLastExecution, threadLastExecution.getChildren())) { - // �Y�����郁�\�b�h���s�����‚��� - return threadLastExecution; - } - threadLastExecution = threadLastTp.getMethodExecution(); - } while (threadLastExecution.getEntryTime() > traceLastTime2); - threadLastPoints.put(traceLastThread, threadLastTp); - traceLastThread = traceLastThread2; - // ���̎��ɒT�����ׂ��X���b�h(���T���̗̈悪��ԍŌ�܂Ŏc���Ă���X���b�h)�����肷�� - traceLastTime2 = 0; - traceLastThread2 = null; - boolean continueTraverse = false; - Iterator threadIterator = threadLastPoints.keySet().iterator(); - for (; threadIterator.hasNext();) { - String threadId = threadIterator.next(); - if (!threadId.equals(traceLastThread)) { - TracePoint lastTp = threadLastPoints.get(threadId); - if (lastTp != null) { - continueTraverse = true; - long threadLastTime = lastTp.getMethodExecution().getEntryTime(); - if (traceLastTime2 < threadLastTime) { - traceLastTime2 = threadLastTime; - traceLastThread2 = threadId; - } - } - } - } - if (!continueTraverse && threadLastPoints.get(traceLastThread) == null) break; - } - return null; - } - - /** - * ���\�b�h���� methodSignature�@�ɑO����v���郁�\�b�h���s��S�ẴX���b�h������o�� - * @param methodSignature ���������� - * @return ��v�����S���\�b�h���s - */ - public ArrayList getMethodExecutions(final String methodSignature) { - Iterator threadsIterator = threads.keySet().iterator(); - final ArrayList results = new ArrayList(); - for (; threadsIterator.hasNext();) { - ThreadInstance thread = threads.get(threadsIterator.next()); - thread.traverseMethodExecutionsBackward(new IMethodExecutionVisitor() { - @Override - public boolean preVisitThread(ThreadInstance thread) { - return false; - } - @Override - public boolean preVisitMethodExecution(MethodExecution methodExecution) { - if (methodExecution.getSignature().startsWith(methodSignature)) { - results.add(methodExecution); - } - return false; - } - @Override - public boolean postVisitThread(ThreadInstance thread) { - return false; - } - @Override - public boolean postVisitMethodExecution(MethodExecution methodExecution, ArrayList children) { - return false; - } - }); - } - return results; + public HashMap getAllThreads() { + return threads; } /** @@ -448,20 +251,6 @@ } /** - * �Ăяo�����̎����� markStart ���� markEnd �̊Ԃɂ���S�X���b�h���̑S���\�b�h���s��T������ - * @param visitor�@�r�W�^�[ - * @param markStart �J�n���� - * @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()); - thread.traverseMarkedMethodExecutions(visitor, markStart, markEnd); - } - } - - /** * �S���\�b�h�̃V�O�j�`�����擾���� * @return �S���\�b�h�V�O�j�`�� */ @@ -494,6 +283,84 @@ } /** + * ���\�b�h���� methodSignature�@�ɑO����v���郁�\�b�h���s��S�ẴX���b�h������o�� + * @param methodSignature ���������� + * @return ��v�����S���\�b�h���s + */ + public ArrayList getMethodExecutions(final String methodSignature) { + Iterator threadsIterator = threads.keySet().iterator(); + final ArrayList results = new ArrayList(); + for (; threadsIterator.hasNext();) { + ThreadInstance thread = threads.get(threadsIterator.next()); + thread.traverseMethodExecutionsBackward(new IMethodExecutionVisitor() { + @Override + public boolean preVisitThread(ThreadInstance thread) { + return false; + } + @Override + public boolean preVisitMethodExecution(MethodExecution methodExecution) { + if (methodExecution.getSignature().startsWith(methodSignature)) { + results.add(methodExecution); + } + return false; + } + @Override + public boolean postVisitThread(ThreadInstance thread) { + return false; + } + @Override + public boolean postVisitMethodExecution(MethodExecution methodExecution, ArrayList children) { + return false; + } + }); + } + return results; + } + + /** + * methodSignature �ɑO����v���郁�\�b�h�������ƒ��\�b�h�̍Ō�̎��s + * @param methodSignature ���\�b�h��(�O����v�Ō�������) + * @return �Y������Ō�̃��\�b�h���s + */ + public MethodExecution getLastMethodExecution(final String methodSignature) { + return traverseMethodEntriesInTraceBackward(new IMethodExecutionVisitor() { + @Override + public boolean preVisitThread(ThreadInstance thread) { return false; } + @Override + public boolean postVisitThread(ThreadInstance thread) { return false; } + @Override + public boolean preVisitMethodExecution(MethodExecution methodExecution) { return false; } + @Override + public boolean postVisitMethodExecution(MethodExecution methodExecution, ArrayList children) { + if (methodExecution.getSignature().startsWith(methodSignature)) return true; + return false; + } + }); + } + + /** + * methodSignature �ɑO����v���郁�\�b�h�������ƒ��\�b�h�� before �ȑO�̍Ō�̎��s + * @param methodSignature ���\�b�h��(�O����v�Ō�������) + * @param before�@�T���J�n�g���[�X�|�C���g(������ȑO��T��) + * @return�@�Y������Ō�̃��\�b�h���s + */ + public MethodExecution getLastMethodExecution(final String methodSignature, TracePoint before) { + return traverseMethodEntriesInTraceBackward(new IMethodExecutionVisitor() { + @Override + public boolean preVisitThread(ThreadInstance thread) { return false; } + @Override + public boolean postVisitThread(ThreadInstance thread) { return false; } + @Override + public boolean preVisitMethodExecution(MethodExecution methodExecution) { return false; } + @Override + public boolean postVisitMethodExecution(MethodExecution methodExecution, ArrayList children) { + if (methodExecution.getSignature().startsWith(methodSignature)) return true; + return false; + } + }, before); + } + + /** * �}�[�N���Ŏ��s���J�n���ꂽ�S���\�b�h�̃V�O�j�`�����擾���� * @param markStart �}�[�N�̊J�n���� * @param markEnd �}�[�N�̏I������ @@ -598,6 +465,405 @@ return executions; } + + private TracePoint getLastMethodEntryInThread(ArrayList rootExecutions) { + MethodExecution lastExecution = rootExecutions.remove(rootExecutions.size() - 1); + return getLastMethodEntryInThread(rootExecutions, lastExecution.getExitOutPoint()); + } + + private TracePoint getLastMethodEntryInThread(ArrayList rootExecutions, TracePoint start) { + return getLastMethodEntryInThread(rootExecutions, start, -1L); + } + + /** + * + * @param rootExecutions + * @param start + * @param before + * @return + */ + private TracePoint getLastMethodEntryInThread(ArrayList rootExecutions, TracePoint start, final long before) { + final TracePoint cp[] = new TracePoint[1]; + cp[0] = start; + for (;;) { + if (!cp[0].isStepBackOut() && traverseMethodExecutionsInCallTreeBackward( + new IMethodExecutionVisitor() { + @Override + public boolean preVisitThread(ThreadInstance thread) { return false; } + @Override + public boolean preVisitMethodExecution(MethodExecution methodExecution) { return false; } + @Override + public boolean postVisitThread(ThreadInstance thread) { return false; } + @Override + public boolean postVisitMethodExecution(MethodExecution methodExecution, ArrayList children) { + if (methodExecution.getEntryTime() < before || before == -1L) { + cp[0] = methodExecution.getEntryPoint(); + return true; + } + return false; + } + }, cp[0])) { + return cp[0]; + } + if (rootExecutions.size() == 0) break; + MethodExecution lastExecution = rootExecutions.remove(rootExecutions.size() - 1); + cp[0] = lastExecution.getExitOutPoint(); + } + return null; + } + + public TracePoint getCreationTracePoint(final ObjectReference newObjectId, TracePoint before) { + before = before.duplicate(); + before = traverseStatementsInTraceBackward( + new IStatementVisitor() { + @Override + public boolean preVisitStatement(Statement statement) { + if (statement instanceof MethodInvocation) { + MethodInvocation mi = (MethodInvocation)statement; + if (mi.getCalledMethodExecution().isConstructor() + && mi.getCalledMethodExecution().getReturnValue().equals(newObjectId)) { + return true; + } + } + return false; + } + @Override + public boolean postVisitStatement(Statement statement) { return false; } + }, before); + if (before != null) { + return before; + } + return null; + } + + public TracePoint getFieldUpdateTracePoint(final Reference ref, TracePoint before) { + before = before.duplicate(); + final String srcType = ref.getSrcClassName(); + final String dstType = ref.getDstClassName(); + final String srcObjId = ref.getSrcObjectId(); + final String dstObjId = ref.getDstObjectId(); + + before = traverseStatementsInTraceBackward(new IStatementVisitor() { + @Override + public boolean preVisitStatement(Statement statement) { + if (statement instanceof FieldUpdate) { + FieldUpdate fu = (FieldUpdate)statement; + if (fu.getContainerObjId().equals(srcObjId) + && fu.getValueObjId().equals(dstObjId)) { + // �I�u�W�F�N�gID���݂��Ɉ�v�����ꍇ + return true; + } else if ((srcObjId == null || isNull(srcObjId)) && fu.getContainerClassName().equals(srcType)) { + if ((dstObjId == null || isNull(dstObjId)) && fu.getValueClassName().equals(dstType)) { + // ref �ɃI�u�W�F�N�gID���w�肵�Ă��Ȃ������ꍇ + ref.setSrcObjectId(fu.getContainerObjId()); + ref.setDstObjectId(fu.getValueObjId()); + return true; + } else if (fu.getValueObjId().equals(dstObjId)) { + // �N���X�ϐ��ւ̑���̏ꍇ + ref.setSrcObjectId(srcObjId); + ref.setDstClassName(dstType); + return true; + } + } + } + return false; + } + @Override + public boolean postVisitStatement(Statement statement) { return false; } + }, before); + if (before != null) { + return before; + } + return null; + } + + public TracePoint getCollectionAddTracePoint(final Reference ref, TracePoint before) { + final TracePoint[] result = new TracePoint[1]; + if (traverseMethodEntriesInTraceBackward(new IMethodExecutionVisitor() { + @Override + public boolean preVisitThread(ThreadInstance thread) { + return false; + } + @Override + public boolean postVisitThread(ThreadInstance thread) { + return false; + } + @Override + public boolean preVisitMethodExecution(MethodExecution methodExecution) { + return false; + } + @Override + public boolean postVisitMethodExecution(MethodExecution methodExecution, ArrayList children) { + String srcType = ref.getSrcClassName(); + String dstType = ref.getDstClassName(); + String srcObjId = ref.getSrcObjectId(); + String dstObjId = ref.getDstObjectId(); + if (methodExecution.isCollectionType() && isCollectionAdd(methodExecution.getSignature())) { + if (dstObjId != null && methodExecution.getThisObjId().equals(srcObjId)) { + ArrayList args = methodExecution.getArguments(); + for (int i = 0; i < args.size(); i++) { + ObjectReference arg = args.get(i); + if (arg.getId().equals(dstObjId)) { + ref.setSrcClassName(methodExecution.getThisClassName()); + ref.setDstClassName(arg.getActualType()); + result[0] = methodExecution.getCallerTracePoint(); + return true; + } + } + } else if (dstObjId == null && methodExecution.getThisClassName().equals(srcType)) { + ArrayList args = methodExecution.getArguments(); + for (int i = 0; i < args.size(); i++) { + ObjectReference arg = args.get(i); + if (arg.getActualType().equals(dstType)) { + ref.setSrcObjectId(methodExecution.getThisObjId()); + ref.setDstObjectId(arg.getId()); + result[0] = methodExecution.getCallerTracePoint(); + return true; + } + } + } + } + return false; + } + }, before) != null) { + return result[0]; + } + return null; + } + + public TracePoint getArraySetTracePoint(final Reference ref, TracePoint before) { + final TracePoint start = before.duplicate(); + before = traverseStatementsInTraceBackward(new IStatementVisitor() { + @Override + public boolean preVisitStatement(Statement statement) { + if (statement instanceof FieldAccess) { + if (isArraySet(ref, start)) { + return true; + } + } + return false; + } + @Override + public boolean postVisitStatement(Statement statement) { return false; } + }, start); + if (before != null) { + return before; + } + return null; + } + + private boolean isCollectionAdd(String methodSignature) { + return (methodSignature.contains("add(") || methodSignature.contains("set(") || methodSignature.contains("put(") || methodSignature.contains("push(")); + } + + private boolean isArraySet(Reference ref, TracePoint fieldAccessPoint) { + FieldAccess fieldAccess = (FieldAccess)fieldAccessPoint.getStatement(); + String srcObjId = ref.getSrcObjectId(); + String dstObjId = ref.getDstObjectId(); + if (fieldAccess.getValueClassName().startsWith("[L") + && fieldAccess.getValueObjId().equals(srcObjId)) { + // srcId �͔z�� + // ���\�b�h���s�J�n���� fieldAccessPoint �܂ł̊Ԃ̃��\�b�h���s���� dstId ���o��������? + TracePoint p = fieldAccessPoint.duplicate(); + while (p.stepBackOver()) { + Statement statement = p.getStatement(); + if (statement instanceof MethodInvocation) { + MethodExecution calledMethod = ((MethodInvocation)statement).getCalledMethodExecution(); + if (calledMethod.getReturnValue().getId().equals(dstObjId)) { + // dstId �͖߂�l�Ƃ��ďo�� + ref.setSrcClassName(fieldAccess.getValueClassName()); + ref.setDstClassName(calledMethod.getReturnValue().getActualType()); + return true; + } else if (dstObjId == null || isNull(dstObjId) && calledMethod.getReturnValue().getActualType().equals(ref.getDstClassName())) { + // dstClassName �͖߂�l�̌^�Ƃ��ďo�� + ref.setSrcObjectId(fieldAccess.getValueObjId()); + ref.setDstObjectId(calledMethod.getReturnValue().getId()); + return true; + } + } + if (EAGER_DETECTION_OF_ARRAY_SET) { + if (statement instanceof FieldAccess) { + if (((FieldAccess)statement).getContainerObjId().equals(dstObjId)) { + // dstId �̓t�B�[���h�ɏo�� + ref.setSrcClassName(fieldAccess.getValueClassName()); + ref.setDstClassName(((FieldAccess)statement).getContainerClassName()); + return true; + } else if (dstObjId == null || isNull(dstObjId) && ((FieldAccess)statement).getContainerClassName().equals(ref.getDstClassName())) { + // dstClassName �̓t�B�[���h�̌^�Ƃ��ďo�� + ref.setSrcObjectId(fieldAccess.getValueObjId()); + ref.setDstObjectId(((FieldAccess)statement).getContainerObjId()); + return true; + } + } + } + } + ArrayList args = fieldAccessPoint.getMethodExecution().getArguments(); + int argindex = args.indexOf(new ObjectReference(dstObjId)); + if (argindex != -1) { + // dstId �͈����ɏo�� + ref.setSrcClassName(fieldAccess.getValueClassName()); + ref.setDstClassName(args.get(argindex).getActualType()); + return true; + } else if (dstObjId == null || isNull(dstObjId)) { + for (int j = 0; j < args.size(); j++) { + if (args.get(j).getActualType().equals(ref.getDstClassName())) { + // dstClassName �͈����̌^�ɏo�� + ref.setSrcObjectId(fieldAccess.getValueObjId()); + ref.setDstObjectId(args.get(j).getId()); + return true; + } + } + } + } + return false; + } + + /** + * �g���[�X���̑S���\�b�h���s�̊J�n�n�_���t�����ɒT������ + * @param visitor ���\�b�h���s�̃r�W�^�[(postVisitMethodExecution()�����ĂѕԂ��Ȃ��̂Œ���) + * @return ���f�������\�b�h���s + */ + 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(); + ThreadInstance thread = threads.get(threadId); + ArrayList rootExecutions = (ArrayList)thread.getRoot().clone(); + threadRoots.put(threadId, rootExecutions); + TracePoint threadLastTp = getLastMethodEntryInThread(rootExecutions); + threadLastPoints.put(threadId, threadLastTp); + if (threadLastTp != null) { + long threadLastTime = threadLastTp.getMethodExecution().getEntryTime(); + if (traceLastTime < threadLastTime) { + traceLastTime2 = traceLastTime; + traceLastThread2 = traceLastThread; + traceLastTime = threadLastTime; + traceLastThread = threadId; + } + } + } + return traverseMethodEntriesInTraceBackwardSub(visitor, threadRoots, threadLastPoints, traceLastThread, traceLastThread2, traceLastTime2); + } + + /** + * �w�肵�����s���_�ȑO�Ɏ��s���J�n���ꂽ���\�b�h���s�̊J�n���_���t�����ɒT������ + * @param visitor ���\�b�h���s�̃r�W�^�[(postVisitMethodExecution()�����ĂѕԂ��Ȃ��̂Œ���) + * @param before �T���J�n���_ + * @return ���f�������\�b�h���s + */ + 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; + ThreadInstance thread = threads.get(before.getStatement().getThreadNo()); + ArrayList rootExecutions = (ArrayList)thread.getRoot().clone(); + for (int n = rootExecutions.size() - 1; n >= 0; n--) { + MethodExecution root = rootExecutions.get(n); + if (root.getEntryTime() > before.getMethodExecution().getEntryTime()) { + rootExecutions.remove(n); + } else { + break; + } + } + if (rootExecutions.size() > 0) { + rootExecutions.remove(rootExecutions.size() - 1); + } + before = getLastMethodEntryInThread(rootExecutions, before); + for (; threadsIterator.hasNext();) { + String threadId = threadsIterator.next(); + ThreadInstance t = threads.get(threadId); + if (t == thread) { + threadRoots.put(threadId, rootExecutions); + traceLastThread = threadId; + threadLastPoints.put(threadId, before); + } else { + ArrayList rootExes = (ArrayList)t.getRoot().clone(); + threadRoots.put(threadId, rootExes); + MethodExecution threadLastExecution = rootExes.remove(rootExes.size() - 1); + TracePoint threadBeforeTp = getLastMethodEntryInThread(rootExes, threadLastExecution.getExitOutPoint(), before.getMethodExecution().getEntryTime()); + threadLastPoints.put(threadId, threadBeforeTp); + if (threadBeforeTp != null) { + long threadLastTime = threadBeforeTp.getMethodExecution().getEntryTime(); + if (traceLastTime2 < threadLastTime) { + traceLastTime2 = threadLastTime; + traceLastThread2 = threadId; + } + } + } + } + return traverseMethodEntriesInTraceBackwardSub(visitor, threadRoots, threadLastPoints, traceLastThread, traceLastThread2, traceLastTime2); + } + + private MethodExecution traverseMethodEntriesInTraceBackwardSub( + final IMethodExecutionVisitor visitor, + HashMap> threadRoots, HashMap threadLastPoints, + String traceLastThread, String traceLastThread2, long traceLastTime2) { + // �S�X���b�h�̓������Ƃ�Ȃ���t�����Ƀ��\�b�h���s��T������ + for (;;) { + // �T���Ώۂ̃X���b�h���̋t�����T�� + TracePoint threadLastTp = threadLastPoints.get(traceLastThread); + MethodExecution threadLastExecution = threadLastTp.getMethodExecution(); + do { + threadLastTp.stepBackOver(); + // ���̃X���b�h�̎��̃��\�b�h���s�J�n���_�܂ŒT������ + threadLastTp = getLastMethodEntryInThread(threadRoots.get(traceLastThread), threadLastTp); + if (threadLastTp == null) break; + if (visitor.postVisitMethodExecution(threadLastExecution, threadLastExecution.getChildren())) { + // �Y�����郁�\�b�h���s�����‚��� + return threadLastExecution; + } + threadLastExecution = threadLastTp.getMethodExecution(); + } while (threadLastExecution.getEntryTime() > traceLastTime2); + threadLastPoints.put(traceLastThread, threadLastTp); + traceLastThread = traceLastThread2; + // ���̎��ɒT�����ׂ��X���b�h(���T���̗̈悪��ԍŌ�܂Ŏc���Ă���X���b�h)�����肷�� + traceLastTime2 = 0; + traceLastThread2 = null; + boolean continueTraverse = false; + Iterator threadIterator = threadLastPoints.keySet().iterator(); + for (; threadIterator.hasNext();) { + String threadId = threadIterator.next(); + if (!threadId.equals(traceLastThread)) { + TracePoint lastTp = threadLastPoints.get(threadId); + if (lastTp != null) { + continueTraverse = true; + long threadLastTime = lastTp.getMethodExecution().getEntryTime(); + if (traceLastTime2 < threadLastTime) { + traceLastTime2 = threadLastTime; + traceLastThread2 = threadId; + } + } + } + } + if (!continueTraverse && threadLastPoints.get(traceLastThread) == null) break; + } + return null; + } + + /** + * �Ăяo�����̎����� markStart ���� markEnd �̊Ԃɂ���S�X���b�h���̑S���\�b�h���s��T������ + * @param visitor�@�r�W�^�[ + * @param markStart �J�n���� + * @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()); + thread.traverseMarkedMethodExecutions(visitor, markStart, markEnd); + } + } + /** * �g���[�X���̑S�X���b�h�𓯊������Ȃ炪�S���s�����������ɒT������ * @@ -856,52 +1122,6 @@ } return null; } - - private TracePoint getLastMethodEntryInThread(ArrayList rootExecutions) { - MethodExecution lastExecution = rootExecutions.remove(rootExecutions.size() - 1); - return getLastMethodEntryInThread(rootExecutions, lastExecution.getExitOutPoint()); - } - - private TracePoint getLastMethodEntryInThread(ArrayList rootExecutions, TracePoint start) { - return getLastMethodEntryInThread(rootExecutions, start, -1L); - } - - /** - * - * @param rootExecutions - * @param start - * @param before - * @return - */ - private TracePoint getLastMethodEntryInThread(ArrayList rootExecutions, TracePoint start, final long before) { - final TracePoint cp[] = new TracePoint[1]; - cp[0] = start; - for (;;) { - if (!cp[0].isStepBackOut() && traverseMethodExecutionsInCallTreeBackward( - new IMethodExecutionVisitor() { - @Override - public boolean preVisitThread(ThreadInstance thread) { return false; } - @Override - public boolean preVisitMethodExecution(MethodExecution methodExecution) { return false; } - @Override - public boolean postVisitThread(ThreadInstance thread) { return false; } - @Override - public boolean postVisitMethodExecution(MethodExecution methodExecution, ArrayList children) { - if (methodExecution.getEntryTime() < before || before == -1L) { - cp[0] = methodExecution.getEntryPoint(); - return true; - } - return false; - } - }, cp[0])) { - return cp[0]; - } - if (rootExecutions.size() == 0) break; - MethodExecution lastExecution = rootExecutions.remove(rootExecutions.size() - 1); - cp[0] = lastExecution.getExitOutPoint(); - } - return null; - } /** * before �Ŏw�肵���g���[�X�|�C���g�ȑO�̓���Ăяo���ؓ��̑S���s�����t�����ɒT������(�������Avisitor �� true ��Ԃ��܂�) @@ -969,212 +1189,6 @@ return false; } - public TracePoint getCreationTracePoint(final ObjectReference newObjectId, TracePoint before) { - before = before.duplicate(); - before = traverseStatementsInTraceBackward( - new IStatementVisitor() { - @Override - public boolean preVisitStatement(Statement statement) { - if (statement instanceof MethodInvocation) { - MethodInvocation mi = (MethodInvocation)statement; - if (mi.getCalledMethodExecution().isConstructor() - && mi.getCalledMethodExecution().getReturnValue().equals(newObjectId)) { - return true; - } - } - return false; - } - @Override - public boolean postVisitStatement(Statement statement) { return false; } - }, before); - if (before != null) { - return before; - } - return null; - } - - public TracePoint getFieldUpdateTracePoint(final Reference ref, TracePoint before) { - before = before.duplicate(); - final String srcType = ref.getSrcClassName(); - final String dstType = ref.getDstClassName(); - final String srcObjId = ref.getSrcObjectId(); - final String dstObjId = ref.getDstObjectId(); - - before = traverseStatementsInTraceBackward(new IStatementVisitor() { - @Override - public boolean preVisitStatement(Statement statement) { - if (statement instanceof FieldUpdate) { - FieldUpdate fu = (FieldUpdate)statement; - if (fu.getContainerObjId().equals(srcObjId) - && fu.getValueObjId().equals(dstObjId)) { - // �I�u�W�F�N�gID���݂��Ɉ�v�����ꍇ - return true; - } else if ((srcObjId == null || isNull(srcObjId)) && fu.getContainerClassName().equals(srcType)) { - if ((dstObjId == null || isNull(dstObjId)) && fu.getValueClassName().equals(dstType)) { - // ref �ɃI�u�W�F�N�gID���w�肵�Ă��Ȃ������ꍇ - ref.setSrcObjectId(fu.getContainerObjId()); - ref.setDstObjectId(fu.getValueObjId()); - return true; - } else if (fu.getValueObjId().equals(dstObjId)) { - // �N���X�ϐ��ւ̑���̏ꍇ - ref.setSrcObjectId(srcObjId); - ref.setDstClassName(dstType); - return true; - } - } - } - return false; - } - @Override - public boolean postVisitStatement(Statement statement) { return false; } - }, before); - if (before != null) { - return before; - } - return null; - } - - public TracePoint getCollectionAddTracePoint(final Reference ref, TracePoint before) { - final TracePoint[] result = new TracePoint[1]; - if (traverseMethodEntriesInTraceBackward(new IMethodExecutionVisitor() { - @Override - public boolean preVisitThread(ThreadInstance thread) { - return false; - } - @Override - public boolean postVisitThread(ThreadInstance thread) { - return false; - } - @Override - public boolean preVisitMethodExecution(MethodExecution methodExecution) { - return false; - } - @Override - public boolean postVisitMethodExecution(MethodExecution methodExecution, ArrayList children) { - String srcType = ref.getSrcClassName(); - String dstType = ref.getDstClassName(); - String srcObjId = ref.getSrcObjectId(); - String dstObjId = ref.getDstObjectId(); - if (methodExecution.isCollectionType() && isCollectionAdd(methodExecution.getSignature())) { - if (dstObjId != null && methodExecution.getThisObjId().equals(srcObjId)) { - ArrayList args = methodExecution.getArguments(); - for (int i = 0; i < args.size(); i++) { - ObjectReference arg = args.get(i); - if (arg.getId().equals(dstObjId)) { - ref.setSrcClassName(methodExecution.getThisClassName()); - ref.setDstClassName(arg.getActualType()); - result[0] = methodExecution.getCallerTracePoint(); - return true; - } - } - } else if (dstObjId == null && methodExecution.getThisClassName().equals(srcType)) { - ArrayList args = methodExecution.getArguments(); - for (int i = 0; i < args.size(); i++) { - ObjectReference arg = args.get(i); - if (arg.getActualType().equals(dstType)) { - ref.setSrcObjectId(methodExecution.getThisObjId()); - ref.setDstObjectId(arg.getId()); - result[0] = methodExecution.getCallerTracePoint(); - return true; - } - } - } - } - return false; - } - }, before) != null) { - return result[0]; - } - return null; - } - - private boolean isCollectionAdd(String methodSignature) { - return (methodSignature.contains("add(") || methodSignature.contains("set(") || methodSignature.contains("put(") || methodSignature.contains("push(")); - } - - public TracePoint getArraySetTracePoint(final Reference ref, TracePoint before) { - final TracePoint start = before.duplicate(); - before = traverseStatementsInTraceBackward(new IStatementVisitor() { - @Override - public boolean preVisitStatement(Statement statement) { - if (statement instanceof FieldAccess) { - if (isArraySet(ref, start)) { - return true; - } - } - return false; - } - @Override - public boolean postVisitStatement(Statement statement) { return false; } - }, start); - if (before != null) { - return before; - } - return null; - } - - private boolean isArraySet(Reference ref, TracePoint fieldAccessPoint) { - FieldAccess fieldAccess = (FieldAccess)fieldAccessPoint.getStatement(); - String srcObjId = ref.getSrcObjectId(); - String dstObjId = ref.getDstObjectId(); - if (fieldAccess.getValueClassName().startsWith("[L") - && fieldAccess.getValueObjId().equals(srcObjId)) { - // srcId �͔z�� - // ���\�b�h���s�J�n���� fieldAccessPoint �܂ł̊Ԃ̃��\�b�h���s���� dstId ���o��������? - TracePoint p = fieldAccessPoint.duplicate(); - while (p.stepBackOver()) { - Statement statement = p.getStatement(); - if (statement instanceof MethodInvocation) { - MethodExecution calledMethod = ((MethodInvocation)statement).getCalledMethodExecution(); - if (calledMethod.getReturnValue().getId().equals(dstObjId)) { - // dstId �͖߂�l�Ƃ��ďo�� - ref.setSrcClassName(fieldAccess.getValueClassName()); - ref.setDstClassName(calledMethod.getReturnValue().getActualType()); - return true; - } else if (dstObjId == null || isNull(dstObjId) && calledMethod.getReturnValue().getActualType().equals(ref.getDstClassName())) { - // dstClassName �͖߂�l�̌^�Ƃ��ďo�� - ref.setSrcObjectId(fieldAccess.getValueObjId()); - ref.setDstObjectId(calledMethod.getReturnValue().getId()); - return true; - } - } - if (EAGER_DETECTION_OF_ARRAY_SET) { - if (statement instanceof FieldAccess) { - if (((FieldAccess)statement).getContainerObjId().equals(dstObjId)) { - // dstId �̓t�B�[���h�ɏo�� - ref.setSrcClassName(fieldAccess.getValueClassName()); - ref.setDstClassName(((FieldAccess)statement).getContainerClassName()); - return true; - } else if (dstObjId == null || isNull(dstObjId) && ((FieldAccess)statement).getContainerClassName().equals(ref.getDstClassName())) { - // dstClassName �̓t�B�[���h�̌^�Ƃ��ďo�� - ref.setSrcObjectId(fieldAccess.getValueObjId()); - ref.setDstObjectId(((FieldAccess)statement).getContainerObjId()); - return true; - } - } - } - } - ArrayList args = fieldAccessPoint.getMethodExecution().getArguments(); - int argindex = args.indexOf(new ObjectReference(dstObjId)); - if (argindex != -1) { - // dstId �͈����ɏo�� - ref.setSrcClassName(fieldAccess.getValueClassName()); - ref.setDstClassName(args.get(argindex).getActualType()); - return true; - } else if (dstObjId == null || isNull(dstObjId)) { - for (int j = 0; j < args.size(); j++) { - if (args.get(j).getActualType().equals(ref.getDstClassName())) { - // dstClassName �͈����̌^�ɏo�� - ref.setSrcObjectId(fieldAccess.getValueObjId()); - ref.setDstObjectId(args.get(j).getId()); - return true; - } - } - } - } - return false; - } - public static String getDeclaringType(String methodSignature, boolean isConstructor) { if (isConstructor) { String[] fragments = methodSignature.split("\\(");