org.adoptopenjdk.jitwatch.model.AbstractMetaMember Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jitwatch-jarscan-maven-plugin Show documentation
Show all versions of jitwatch-jarscan-maven-plugin Show documentation
A Maven plugin that scans the project artifact and its dependencies for methods that cannot be inlined by the JIT
compiler. It uses the JarScan utility from the JITWatch project to do that.
See https://github.com/AdoptOpenJDK/jitwatch .
The newest version!
/*
* 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.model;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.C_CLOSE_PARENTHESES;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.C_COMMA;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.C_DOLLAR;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.C_DOT;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.C_HAT;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.C_OPEN_PARENTHESES;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.C_OPEN_SQUARE_BRACKET;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.C_SPACE;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.DEBUG_LOGGING_ASSEMBLY;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.DEBUG_LOGGING_SIG_MATCH;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.REGEX_GROUP_ANY;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.REGEX_ONE_OR_MORE_SPACES;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.REGEX_UNICODE_PACKAGE_NAME;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.REGEX_UNICODE_PARAM_NAME;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.REGEX_ZERO_OR_MORE_SPACES;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_CLOSE_SQUARE;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_COMMA;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_DOT;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_EMPTY;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_ESCAPED_CLOSE_PARENTHESES;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_ESCAPED_CLOSE_SQUARE;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_ESCAPED_OPEN_PARENTHESES;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_ESCAPED_OPEN_SQUARE;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_OPEN_SQUARE;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_POLYMORPHIC_SIGNATURE;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.adoptopenjdk.jitwatch.model.assembly.AssemblyMethod;
import org.adoptopenjdk.jitwatch.model.bytecode.BytecodeInstruction;
import org.adoptopenjdk.jitwatch.model.bytecode.ClassBC;
import org.adoptopenjdk.jitwatch.model.bytecode.MemberBytecode;
import org.adoptopenjdk.jitwatch.util.ParseUtil;
import org.adoptopenjdk.jitwatch.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public abstract class AbstractMetaMember implements IMetaMember, Comparable
{
protected static final Logger logger = LoggerFactory.getLogger(AbstractMetaMember.class);
protected MetaClass metaClass;
private List assemblyMethods = new ArrayList<>();
private boolean isQueued = false;
private boolean isCompiled = false;
private Journal journal = new Journal();
private Map queuedAttributes = new ConcurrentHashMap<>();
private Map compiledAttributes = new ConcurrentHashMap<>();
protected boolean isVarArgs = false;
protected boolean isPolymorphicSignature = false;
protected int modifier; // bitset
private String memberName;
protected Class> returnType;
protected List> paramTypes;
public AbstractMetaMember(String memberName)
{
this.memberName = memberName;
}
protected void checkPolymorphicSignature(Method method)
{
for (Annotation anno : method.getAnnotations())
{
if (S_POLYMORPHIC_SIGNATURE.equals(anno.annotationType().getSimpleName()))
{
isPolymorphicSignature = true;
break;
}
}
}
@Override
public String getMemberName()
{
return memberName;
}
@Override
public String getFullyQualifiedMemberName()
{
return metaClass.getFullyQualifiedName() + C_DOT + memberName;
}
@Override
public String getAbbreviatedFullyQualifiedMemberName()
{
return metaClass.getAbbreviatedFullyQualifiedName() + C_DOT + memberName;
}
@Override
public int getModifier()
{
return modifier;
}
@Override
public String getModifierString()
{
return Modifier.toString(modifier);
}
private boolean nameMatches(MemberSignatureParts msp)
{
if (DEBUG_LOGGING_SIG_MATCH)
{
logger.debug("nameMatches this.memberName: '{}' fq: '{}' other '{}' fq: '{}'", memberName, getFullyQualifiedMemberName(), msp.getMemberName(), msp.getFullyQualifiedClassName());
}
boolean match = memberName.equals(msp.getMemberName());
if (DEBUG_LOGGING_SIG_MATCH)
{
logger.debug("nameMatches {}", match);
}
return match;
}
private boolean returnTypeMatches(MemberSignatureParts msp) throws ClassNotFoundException
{
boolean matched = false;
String returnTypeClassName = msp.applyGenericSubstitutionsForClassLoading(msp.getReturnType());
if (returnTypeClassName != null)
{
Class> sigReturnType = ParseUtil.findClassForLogCompilationParameter(returnTypeClassName);
matched = returnType.equals(sigReturnType);
if (DEBUG_LOGGING_SIG_MATCH)
{
logger.debug("Return: '{}' === '{}' ? {}", returnType.getName(), sigReturnType.getName(), matched);
}
}
else
{
matched = (this instanceof MetaConstructor);
if (DEBUG_LOGGING_SIG_MATCH)
{
logger.debug("Constructor found");
}
}
return matched;
}
@Override
public boolean matchesSignature(MemberSignatureParts msp, boolean matchTypesExactly)
{
boolean result = false;
if (nameMatches(msp))
{
if (DEBUG_LOGGING_SIG_MATCH)
{
logger.debug("Comparing:\n--------------\n{}\n--------------\n{}\n--------------", this, msp);
}
if (isPolymorphicSignature)
{
// assumption: method overloading not possible
// with polymorphic signatures so this is a match
if (DEBUG_LOGGING_SIG_MATCH)
{
logger.debug("Member has PolymorphicSignature");
}
result = true;
}
else
{
try
{
if (returnTypeMatches(msp))
{
List> mspClassTypes = getClassesForParamTypes(msp);
if (ParseUtil.paramClassesMatch(isVarArgs, this.paramTypes, mspClassTypes, matchTypesExactly))
{
result = true;
}
}
}
catch (ClassNotFoundException cnfe)
{
logger.error("Class not found while matching signature:\n{}", msp, cnfe);
}
}
if (DEBUG_LOGGING_SIG_MATCH)
{
logger.debug("Match: {}", result);
}
}
return result;
}
private List> getClassesForParamTypes(MemberSignatureParts msp) throws ClassNotFoundException
{
List> result = new ArrayList<>();
for (String param : msp.getParamTypes())
{
String paramClassName = msp.applyGenericSubstitutionsForClassLoading(param);
Class> clazz = ParseUtil.findClassForLogCompilationParameter(paramClassName);
result.add(clazz);
}
return result;
}
@Override
public String getReturnTypeName()
{
return (returnType == null) ? S_EMPTY : ParseUtil.expandParameterType(returnType.getName());
}
@Override
public String[] getParamTypeNames()
{
List typeNames = new ArrayList<>();
for (Class> paramClass : paramTypes)
{
typeNames.add(ParseUtil.expandParameterType(paramClass.getName()));
}
return typeNames.toArray(new String[typeNames.size()]);
}
@Override
public MemberBytecode getMemberBytecode()
{
MemberBytecode result = null;
if (metaClass != null)
{
ClassBC classBytecode = metaClass.getClassBytecode();
if (classBytecode != null)
{
result = classBytecode.getMemberBytecode(this);
}
}
return result;
}
@Override
public List getInstructions()
{
List result = null;
MemberBytecode memberBytecode = getMemberBytecode();
if (memberBytecode != null)
{
result = memberBytecode.getInstructions();
}
else
{
result = new ArrayList<>();
}
return result;
}
@Override
public MetaClass getMetaClass()
{
return metaClass;
}
@Override
public String getQueuedAttribute(String key)
{
return queuedAttributes.get(key);
}
@Override
public String getCompiledAttribute(String key)
{
return compiledAttributes.get(key);
}
@Override
public void addCompiledAttribute(String key, String value)
{
compiledAttributes.put(key, value);
}
@Override
public void setQueuedAttributes(Map queuedAttributes)
{
isQueued = true;
this.queuedAttributes = queuedAttributes;
}
@Override
public boolean isQueued()
{
return isQueued;
}
@Override
public void setCompiledAttributes(Map compiledAttributes)
{
isCompiled = true;
isQueued = false;
this.compiledAttributes = compiledAttributes;
// inform package tree it contains class with a compiled method
getMetaClass().getPackage().setHasCompiledClasses();
}
@Override
public void addCompiledAttributes(Map additionalAttrs)
{
compiledAttributes.putAll(additionalAttrs);
}
@Override
public boolean isCompiled()
{
return isCompiled;
}
@Override
public Map getQueuedAttributes()
{
return queuedAttributes;
}
@Override
public Map getCompiledAttributes()
{
return compiledAttributes;
}
@Override
public String toStringUnqualifiedMethodName(boolean fqParamTypes)
{
StringBuilder builder = new StringBuilder();
if (modifier != 0)
{
builder.append(Modifier.toString(modifier)).append(C_SPACE);
}
if (returnType != null)
{
builder.append(expandParam(returnType.getName(), fqParamTypes)).append(C_SPACE);
}
builder.append(memberName);
builder.append(C_OPEN_PARENTHESES);
if (paramTypes.size() > 0)
{
for (Class> paramClass : paramTypes)
{
builder.append(expandParam(paramClass.getName(), fqParamTypes)).append(C_COMMA);
}
builder.deleteCharAt(builder.length() - 1);
}
builder.append(C_CLOSE_PARENTHESES);
return builder.toString();
}
@Override
public List getAssemblyMethods()
{
return assemblyMethods;
}
@Override
public void addAssembly(AssemblyMethod asmMethod)
{
if (DEBUG_LOGGING_ASSEMBLY)
{
logger.debug("setAssembly on member {}", getFullyQualifiedMemberName());
}
assemblyMethods.add(asmMethod);
}
@Override
public String getSignatureRegEx()
{
StringBuilder builder = new StringBuilder();
builder.append(C_HAT);
builder.append(REGEX_GROUP_ANY);
String modifiers = Modifier.toString(modifier);
if (modifiers.length() > 0)
{
builder.append(modifiers).append(C_SPACE);
}
// return type of constructor is not declared in signature
if (!(this instanceof MetaConstructor) && returnType != null)
{
String rt = expandParamRegEx(returnType.getName());
builder.append(rt);
builder.append(C_SPACE);
}
if (this instanceof MetaConstructor)
{
builder.append(REGEX_UNICODE_PACKAGE_NAME);
builder.append(StringUtil.getUnqualifiedClassName(memberName));
}
else
{
builder.append(memberName);
}
builder.append(REGEX_ZERO_OR_MORE_SPACES);
builder.append(S_ESCAPED_OPEN_PARENTHESES);
if (paramTypes.size() > 0)
{
for (Class> paramClass : paramTypes)
{
builder.append(REGEX_ZERO_OR_MORE_SPACES);
String paramType = expandParamRegEx(paramClass.getName());
builder.append(paramType);
builder.append(REGEX_ONE_OR_MORE_SPACES);
builder.append(REGEX_UNICODE_PARAM_NAME);
builder.append(S_COMMA);
}
builder.deleteCharAt(builder.length() - 1);
}
builder.append(REGEX_ZERO_OR_MORE_SPACES);
builder.append(S_ESCAPED_CLOSE_PARENTHESES);
builder.append(REGEX_GROUP_ANY);
builder.append(C_DOLLAR);
return builder.toString();
}
public static String expandParam(String inParamType, boolean fullyQualifiedType)
{
String paramType = inParamType;
if (paramType.charAt(0) == C_OPEN_SQUARE_BRACKET)
{
paramType = ParseUtil.expandParameterType(paramType);
}
if (paramType.contains(S_DOT) && !fullyQualifiedType)
{
paramType = StringUtil.getUnqualifiedClassName(paramType);
}
return paramType;
}
public static String expandParamRegEx(String inParamType)
{
String paramType = inParamType;
if (paramType.charAt(0) == C_OPEN_SQUARE_BRACKET)
{
paramType = ParseUtil.expandParameterType(paramType);
paramType = paramType.replace(S_OPEN_SQUARE, S_ESCAPED_OPEN_SQUARE).replace(S_CLOSE_SQUARE, S_ESCAPED_CLOSE_SQUARE);
}
if (paramType.contains(S_DOT))
{
paramType = REGEX_UNICODE_PACKAGE_NAME + StringUtil.getUnqualifiedClassName(paramType);
}
return paramType;
}
@Override
public int compareTo(IMetaMember other)
{
if (other == null)
{
return -1;
}
else
{
return getMemberName().compareTo(other.getMemberName());
}
}
@Override
public Journal getJournal()
{
return journal;
}
@Override
public void addJournalEntry(Tag entry)
{
journal.addEntry(entry);
}
}