in core/src/main/java/org/adoptopenjdk/jitwatch/model/bytecode/BytecodeAnnotationBuilder.java [494:748]
private void buildParseTagAnnotations(Tag parseTag, BytecodeAnnotations annotations, IParseDictionary parseDictionary)
throws AnnotationException
{
// Only interested in annotating the current method so
// do not recurse into method or parse tags
if (DEBUG_LOGGING)
{
logger.debug("Building parse tag annotations");
}
List<Tag> children = parseTag.getChildren();
int currentBytecode = -1;
Map<String, Map<String, String>> methodAttrs = new HashMap<>();
Map<String, String> callAttrs = new HashMap<>();
Map<String, String> lastMethodAttrs = new HashMap<>();
String currentMethodID = parseTag.getAttributes().get(ATTR_METHOD);
BytecodeInstruction currentInstruction = null;
for (Tag child : children)
{
String name = child.getName();
Map<String, String> tagAttrs = child.getAttributes();
if (DEBUG_LOGGING_BYTECODE)
{
logger.debug("Examining child tag {}", child);
}
switch (name)
{
case TAG_BC:
{
String bciAttr = tagAttrs.get(ATTR_BCI);
String codeAttr = tagAttrs.get(ATTR_CODE);
currentBytecode = Integer.parseInt(bciAttr);
int code = Integer.parseInt(codeAttr);
callAttrs.clear();
if (DEBUG_LOGGING_BYTECODE)
{
logger.debug("BC Tag {} {}", currentBytecode, code);
}
currentInstruction = getInstructionAtIndex(currentBytecode);
if (DEBUG_LOGGING_BYTECODE)
{
logger.debug("Instruction at {} is {}", currentBytecode, currentInstruction);
}
break;
}
case TAG_CALL:
{
callAttrs.clear();
callAttrs.putAll(tagAttrs);
lastMethodAttrs.clear();
String calleeId = tagAttrs.get("method");
if (calleeId != null)
{
Map<String, String> calleeAttrs = methodAttrs.get(calleeId);
if (calleeAttrs != null)
{
lastMethodAttrs.putAll(calleeAttrs);
}
}
break;
}
case TAG_METHOD:
{
String methodId = tagAttrs.get("id");
if (methodId != null)
{
methodAttrs.put(methodId, tagAttrs);
}
break;
}
case TAG_INLINE_SUCCESS:
{
if (!sanityCheckInline(currentInstruction))
{
throw new AnnotationException("Expected an invoke instruction (in INLINE_SUCCESS)", currentBytecode,
currentInstruction);
}
String reason = tagAttrs.get(ATTR_REASON);
String annotationText = buildInlineAnnotation(parseDictionary, lastMethodAttrs, callAttrs, reason, true);
IMetaMember inlinedMember = ParseUtil.lookupMember(lastMethodAttrs.get(ATTR_ID), parseDictionary, model);
LineAnnotation lineAnnotation = new LineAnnotation(annotationText, BCAnnotationType.INLINE_SUCCESS, inlinedMember);
putAnnotation(currentMember, currentBytecode, lineAnnotation);
break;
}
case TAG_INLINE_FAIL:
{
if (!sanityCheckInline(currentInstruction))
{
throw new AnnotationException("Expected an invoke instruction (in INLINE_FAIL)", currentBytecode,
currentInstruction);
}
String reason = tagAttrs.get(ATTR_REASON);
String annotationText = buildInlineAnnotation(parseDictionary, lastMethodAttrs, callAttrs, reason, false);
IMetaMember inlinedMember = ParseUtil.lookupMember(lastMethodAttrs.get(ATTR_ID), parseDictionary, model);
LineAnnotation lineAnnotation = new LineAnnotation(annotationText, BCAnnotationType.INLINE_FAIL, inlinedMember);
putAnnotation(currentMember, currentBytecode, lineAnnotation);
break;
}
case TAG_BRANCH:
{
if (!sanityCheckBranch(currentInstruction))
{
throw new AnnotationException("Expected a branch instruction (BRANCH)", currentBytecode, currentInstruction);
}
String branchAnnotation = buildBranchAnnotation(tagAttrs);
putAnnotation(currentMember, currentBytecode, new LineAnnotation(branchAnnotation, BCAnnotationType.BRANCH));
break;
}
case TAG_INTRINSIC:
{
if (!sanityCheckIntrinsic(currentInstruction))
{
throw new AnnotationException("Expected an invoke instruction (INTRINSIC)", currentBytecode,
currentInstruction);
}
StringBuilder reason = new StringBuilder();
reason.append("Intrinsic: ").append(tagAttrs.get(ATTR_ID));
putAnnotation(currentMember, currentBytecode,
new LineAnnotation(reason.toString(), BCAnnotationType.INTRINSIC_USED));
break;
}
case TAG_UNCOMMON_TRAP:
{
String trapMethod = child.getAttributes().get(ATTR_METHOD);
if (trapMethod == null || currentMethodID.equals(trapMethod))
{
visitTagUncommonTrap(child);
}
break;
}
case TAG_PHASE:
{
String phaseName = tagAttrs.get(ATTR_NAME);
if (S_PARSE_HIR.equals(phaseName))
{
buildParseTagAnnotations(child, annotations, parseDictionary);
}
else
{
logger.warn("Don't know how to handle phase {}", phaseName);
}
break;
}
case TAG_VIRTUAL_CALL:
putAnnotation(currentMember, currentBytecode,
new LineAnnotation("Virtual call, not inlined", BCAnnotationType.VIRTUAL_CALL));
break;
case TAG_HOT_THROW:
{
MemberBytecode memberBytecode = currentMember.getMemberBytecode();
if (memberBytecode != null)
{
ExceptionTable exceptionTable = memberBytecode.getExceptionTable();
if (exceptionTable != null)
{
ExceptionTableEntry entry = exceptionTable.getEntryForBCI(currentBytecode);
if (entry != null)
{
int exceptionBCI = entry.getTarget();
String exceptionType = entry.getType();
String preallocated = child.getAttributes().get(ATTR_PREALLOCATED);
StringBuilder reason = new StringBuilder();
reason.append(exceptionType.replaceAll(S_SLASH, S_DOT)).append(" thrown by this operation");
BCAnnotationType annotationType;
if (preallocated != null && "1".equals(preallocated))
{
reason.append(" has been pre-allocated.");
annotationType = BCAnnotationType.HOT_THROW_PREALLOCATED;
}
else
{
reason.append(" was not pre-allocated.");
annotationType = BCAnnotationType.HOT_THROW_NOT_PREALLOCATED;
}
putAnnotation(currentMember, exceptionBCI, new LineAnnotation(reason.toString(), annotationType));
}
}
else
{
logger.warn("No ExceptionTable found for {}", currentMember);
}
}
else
{
logger.warn("No MemberBytecode found for {}", currentMember);
}
break;
}
default:
handleOther(child);
break;
}
}
}