/*
* Copyright (c) 2013-2015 Chris Newland.
* Licensed under https://github.com/AdoptOpenJDK/jitwatch/blob/master/LICENSE-BSD
* Instructions: https://github.com/AdoptOpenJDK/jitwatch/wiki
*/
package org.adoptopenjdk.jitwatch.model.bytecode;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.DEBUG_LOGGING_TRIVIEW;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_DOT;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SourceMapper
{
private static final Logger logger = LoggerFactory.getLogger(SourceMapper.class);
private static Map<String, List<ClassBC>> sourceToClassMap = new HashMap<>();
public static void clear()
{
sourceToClassMap.clear();
}
private static String getFullyQualifiedSourceName(ClassBC classBytecode)
{
StringBuilder builder = new StringBuilder();
String packageName = classBytecode.getPackageName();
if (packageName != null && packageName.length() > 0)
{
builder.append(packageName).append(S_DOT);
}
builder.append(classBytecode.getSourceFile());
return builder.toString();
}
public static void addSourceClassMapping(ClassBC classBytecode)
{
String fqName = getFullyQualifiedSourceName(classBytecode);
List<ClassBC> classBytecodeList = sourceToClassMap.get(fqName);
if (classBytecodeList == null)
{
classBytecodeList = new ArrayList<>();
sourceToClassMap.put(fqName, classBytecodeList);
}
classBytecodeList.add(classBytecode);
}
public static List<ClassBC> getClassBytecodeList(ClassBC classBytecode)
{
String fqName = getFullyQualifiedSourceName(classBytecode);
List<ClassBC> result = sourceToClassMap.get(fqName);
if (result == null)
{
result = new ArrayList<>();
}
return Collections.unmodifiableList(result);
}
public static MemberBytecode getMemberBytecodeForSourceLine(ClassBC classBytecode, int sourceLine)
{
MemberBytecode result = null;
String fqName = getFullyQualifiedSourceName(classBytecode);
List<ClassBC> classBytecodeList = sourceToClassMap.get(fqName);
if (classBytecodeList != null)
{
if (DEBUG_LOGGING_TRIVIEW)
{
logger.debug("Found {} ClassBC for source {}", classBytecodeList.size(), fqName);
}
outer: for (ClassBC classBC : classBytecodeList)
{
for (MemberBytecode tempMemberBytecode : classBC.getMemberBytecodeList())
{
LineTable lineTable = tempMemberBytecode.getLineTable();
if (DEBUG_LOGGING_TRIVIEW)
{
logger.debug("Checking LineTable\n{}", lineTable.toString());
}
if (lineTable.sourceLineInRange(sourceLine))
{
result = tempMemberBytecode;
break outer;
}
}
}
}
else
{
logger.warn("No source-bytecode mapping found for class {}", classBytecode.getFullyQualifiedClassName());
}
if (DEBUG_LOGGING_TRIVIEW)
{
logger.debug("Found bytecode offset {}", result);
}
return result;
}
public static int getSourceLineFromBytecode(MemberBytecode memberBytecode, int bytecodeOffset)
{
int result = -1;
if (memberBytecode != null)
{
LineTable lineTable = memberBytecode.getLineTable();
result = lineTable.findSourceLineForBytecodeOffset(bytecodeOffset);
}
return result;
}
}