/*
* Copyright (c) 2013-2016 Chris Newland.
* Licensed under https://github.com/AdoptOpenJDK/jitwatch/blob/master/LICENSE-BSD
* Instructions: https://github.com/AdoptOpenJDK/jitwatch/wiki
*/
package org.adoptopenjdk.jitwatch.jarscan.nextinstruction;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_COMMA;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_NEWLINE;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import org.adoptopenjdk.jitwatch.jarscan.sequencecount.InstructionSequence;
import org.adoptopenjdk.jitwatch.jarscan.sequencecount.SequenceCountOperation;
import org.adoptopenjdk.jitwatch.model.bytecode.Opcode;
public class NextInstructionOperation extends SequenceCountOperation
{
private Map<Opcode, NextInstructionCountList> nextBytecodeMap;
private int maxChildren = 0;
public NextInstructionOperation(int maxChildren)
{
super(2);
this.maxChildren = maxChildren;
}
private void calculate()
{
nextBytecodeMap = new EnumMap<>(Opcode.class);
for (Map.Entry<InstructionSequence, Integer> entry : chainCountMap.entrySet())
{
InstructionSequence sequence = entry.getKey();
Opcode root = sequence.getOpcodeAtIndex(0);
Opcode next = sequence.getOpcodeAtIndex(1);
int count = entry.getValue();
NextInstructionCountList nextBytecodeList = nextBytecodeMap.get(root);
if (nextBytecodeList == null)
{
nextBytecodeList = new NextInstructionCountList();
nextBytecodeMap.put(root, nextBytecodeList);
}
nextBytecodeList.add(new NextInstructionCount(next, count));
}
}
public Map<Opcode, NextInstructionCountList> getNextBytecodeMap()
{
if (nextBytecodeMap == null)
{
calculate();
}
return nextBytecodeMap;
}
@Override
public String getReport()
{
if (nextBytecodeMap == null)
{
calculate();
}
StringBuilder builder = new StringBuilder();
List<Map.Entry<Opcode, NextInstructionCountList>> sortedList = new ArrayList<>(nextBytecodeMap.entrySet());
Collections.sort(sortedList, new Comparator<Map.Entry<Opcode, NextInstructionCountList>>()
{
@Override
public int compare(Map.Entry<Opcode, NextInstructionCountList> o1, Map.Entry<Opcode, NextInstructionCountList> o2)
{
return o1.getKey().getMnemonic().compareTo(o2.getKey().getMnemonic());
}
});
for (Map.Entry<Opcode, NextInstructionCountList> entry : sortedList)
{
Opcode root = entry.getKey();
NextInstructionCountList nextBytecodeList = entry.getValue();
int reportLines = 0;
for (NextInstructionCount nextBytecode : nextBytecodeList.getList())
{
builder.append(root.getMnemonic()).append(S_COMMA).append(nextBytecode.getOpcode().getMnemonic()).append(S_COMMA)
.append(nextBytecode.getCount()).append(S_NEWLINE);
reportLines++;
if (reportLines == maxChildren)
{
break;
}
}
}
return builder.toString();
}
}