org.adoptopenjdk.jitwatch.model.assembly.AssemblyLabels Maven / Gradle / Ivy
Show all versions of jitwatch-jarscan-maven-plugin Show documentation
/*
* Copyright (c) 2013-2015 Chris Newland.
* Copyright (c) 2015 Philip Aston
* Licensed under https://github.com/AdoptOpenJDK/jitwatch/blob/master/LICENSE-BSD
* Instructions: https://github.com/AdoptOpenJDK/jitwatch/wiki
*/
package org.adoptopenjdk.jitwatch.model.assembly;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.C_SPACE;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_ASSEMBLY_ADDRESS;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_COMMA;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedSet;
import java.util.TreeSet;
import org.adoptopenjdk.jitwatch.util.StringUtil;
/**
* Calculate symbolic names for method-local addresses.
*
*
* Operates in two modes. During parsing, {@link #newInstruction(AssemblyInstruction)} accumulates
* addresses used by instructions. After all the instructions have been parsed,
* {@link #buildLabels()} builds an index of addresses of all known instructions
* to label numbers, and {@link #formatAddress} and {@link #formatOperands}
* replace matching addresses with their labels.
*
* @author Philip Aston
*/
public final class AssemblyLabels
{
private SortedSet addresses = new TreeSet<>();
private final Map labels = new HashMap<>();
private long lowest = Long.MAX_VALUE;
private long highest;
public void newInstruction(AssemblyInstruction instruction)
{
final long address = instruction.getAddress();
lowest = Math.min(lowest, address);
highest = Math.max(highest, address);
final Long l = instructionToLabel(instruction);
if (l != null)
{
addresses.add(l);
}
}
private Long instructionToLabel(AssemblyInstruction instruction)
{
final List operands = instruction.getOperands();
if (instruction.getMnemonic().startsWith("j") && operands.size() == 1)
{
return AssemblyUtil.getValueFromAddress(operands.get(0));
}
return null;
}
public void buildLabels()
{
short next = 0;
if (lowest != Long.MAX_VALUE)
{
for (Long a : addresses.subSet(lowest, highest + 1))
{
labels.put(a, next++);
}
}
addresses = null;
}
public void formatAddress(long address, StringBuilder builder)
{
final Short label = labels.get(address);
if (label != null)
{
builder.append(StringUtil.pad(String.format("L%04x", label), 18, C_SPACE, true));
}
else
{
builder.append(S_ASSEMBLY_ADDRESS);
builder.append(StringUtil.pad(Long.toHexString(address), 16, '0', true));
}
}
public void formatOperands(AssemblyInstruction instruction, StringBuilder builder)
{
final Long address = instructionToLabel(instruction);
final Short label = labels.get(address);
if (label != null)
{
builder.append(C_SPACE);
builder.append(String.format("L%04x", label));
}
else
{
final List operands = instruction.getOperands();
if (operands.size() > 0)
{
builder.append(C_SPACE);
for (String op : operands)
{
builder.append(op).append(S_COMMA);
}
builder.deleteCharAt(builder.length() - 1);
}
}
}
}