All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.adoptopenjdk.jitwatch.model.MemberSignatureParts Maven / Gradle / Ivy

Go to download

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_ANGLE;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.C_COMMA;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.C_DOT;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.C_NEWLINE;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.C_OPEN_ANGLE;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.C_QUESTION;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.C_SPACE;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.DEBUG_LOGGING;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.DEBUG_LOGGING_ASSEMBLY;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_BYTECODE_STATIC_INITIALISER_SIGNATURE;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_CLOSE_PARENTHESES;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_COMMA;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_CONSTRUCTOR_INIT;
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_ENTITY_APOS;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_OPEN_PARENTHESES;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_QUOTE;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_SLASH;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_SPACE;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_STATIC_INIT;

import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.adoptopenjdk.jitwatch.model.bytecode.ClassBC;
import org.adoptopenjdk.jitwatch.util.ParseUtil;
import org.adoptopenjdk.jitwatch.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MemberSignatureParts
{
	private String fullyQualifiedClassName;
	private int modifier;
	private List modifierList;
	private Map genericsMap;
	private String returnType;
	private String memberName;
	private List paramTypeList;
	private ClassBC classBytecode;

	private static final Pattern PATTERN_ASSEMBLY_SIGNATURE = Pattern.compile("^(.*)\\s'(.*)'\\s'(\\(.*\\))(.*)'\\sin\\s'(.*)'");

	private static final Logger logger = LoggerFactory.getLogger(MemberSignatureParts.class);

	// LinkedHashMap to ensure entry set iteration matches insertion order
	private static final Map modifierMap = new LinkedHashMap();

	static
	{
		addModifierMapping(Modifier.PUBLIC);
		addModifierMapping(Modifier.PROTECTED);
		addModifierMapping(Modifier.PRIVATE);
		addModifierMapping(Modifier.ABSTRACT);
		addModifierMapping(Modifier.STATIC);
		addModifierMapping(Modifier.FINAL);
		addModifierMapping(Modifier.SYNCHRONIZED);
		addModifierMapping(Modifier.NATIVE);
		addModifierMapping(Modifier.STRICT);
	}

	private static void addModifierMapping(int modifier)
	{
		modifierMap.put(Modifier.toString(modifier), modifier);
	}

	private MemberSignatureParts()
	{
		modifierList = new ArrayList<>();
		genericsMap = new LinkedHashMap<>(); // preserve order
		paramTypeList = new ArrayList<>();
		modifier = 0;
	}

	// TODO really???
	public void setClassBC(ClassBC classBytecode)
	{
		this.classBytecode = classBytecode;
	}

	private static void completeSignature(String origSig, MemberSignatureParts msp)
	{
		if (msp.memberName != null)
		{
			// Constructors will return void for returnType
			if (S_CONSTRUCTOR_INIT.equals(msp.memberName) || msp.memberName.equals(msp.fullyQualifiedClassName))
			{
				msp.memberName = StringUtil.getUnqualifiedClassName(msp.fullyQualifiedClassName);
				msp.returnType = Void.TYPE.getName();

				if (DEBUG_LOGGING)
				{
					logger.debug("Found constructor: {} ", msp.memberName);
				}
			}
		}
		else
		{
			if (DEBUG_LOGGING)
			{
				logger.debug("MemberSignatureParts.memberName was null for signature: '{}'\n{}", origSig, msp);
			}
		}
	}

	public static MemberSignatureParts fromParts(String fullyQualifiedClassName, String memberName, String returnType,
			List paramTypes)
	{
		MemberSignatureParts msp = new MemberSignatureParts();

		msp.fullyQualifiedClassName = fullyQualifiedClassName;

		msp.memberName = memberName;

		msp.paramTypeList.addAll(paramTypes);

		msp.returnType = returnType;

		completeSignature(fullyQualifiedClassName + S_COMMA + memberName + S_COMMA + returnType, msp);

		return msp;
	}

	public static MemberSignatureParts fromLogCompilationSignature(String toParse) throws LogParseException
	{
		MemberSignatureParts msp = new MemberSignatureParts();

		String[] parts = ParseUtil.splitLogSignatureWithRegex(toParse);

		msp.fullyQualifiedClassName = parts[0];
		msp.memberName = parts[1];

		String paramTypes = parts[2];
		String returnType = parts[3];

		setParamsAndReturn(msp, paramTypes, returnType);

		completeSignature(toParse, msp);

		return msp;
	}

	private static boolean isStaticInitialiser(String bytecodeSignature)
	{
		boolean isClinit = false;

		if (bytecodeSignature != null && bytecodeSignature.startsWith(S_BYTECODE_STATIC_INITIALISER_SIGNATURE))
		{
			isClinit = true;
		}

		return isClinit;
	}

	// TODO unit test me!
	public static MemberSignatureParts fromBytecodeComment(String toParse) throws LogParseException
	{
		String logCompilationSignature = ParseUtil.bytecodeCommentSignatureToLogCompilationSignature(toParse);

		return fromLogCompilationSignature(logCompilationSignature);
	}

	public static MemberSignatureParts fromBytecodeSignature(String fqClassName, String toParse)
	{
		MemberSignatureParts msp = new MemberSignatureParts();

		msp.fullyQualifiedClassName = fqClassName;

		if (isStaticInitialiser(toParse))
		{
			msp.memberName = S_STATIC_INIT;
			msp.returnType = Void.TYPE.getName();

			return msp;
		}

		StringBuilder builder = new StringBuilder();

		builder.append("^[ ]*");

		for (String mod : modifierMap.keySet())
		{
			builder.append(S_OPEN_PARENTHESES).append(mod).append(S_SPACE).append(S_CLOSE_PARENTHESES).append(C_QUESTION);
		}

		String regexGenerics = "(<[\\p{L}0-9_\\.\\$\\ ,/]+> )?";
		String regexReturnType = "(.* )?"; // optional could be constructor
		String regexMethodName = ParseUtil.METHOD_NAME_REGEX_GROUP;
		String regexParams = "(\\(.*\\))";
		String regexRest = "(.*)";

		builder.append(regexGenerics);
		builder.append(regexReturnType);
		builder.append(regexMethodName);
		builder.append(regexParams);
		builder.append(regexRest);

		// logger.info("\n{}\n{}", toParse, builder);

		final Pattern patternBytecodeSignature = Pattern.compile(builder.toString());

		Matcher matcher = patternBytecodeSignature.matcher(toParse);

		int modifierCount = modifierMap.size();

		if (matcher.find())
		{
			int count = matcher.groupCount();

			for (int i = 1; i < count; i++)
			{
				String group = matcher.group(i);

				if (group != null)
				{
					group = group.trim();
				}

				if (group != null && i <= modifierCount)
				{
					msp.modifierList.add(group);

					// add bitset value for this modifier
					msp.modifier += modifierMap.get(group);
				}

				if (i == modifierCount + 1)
				{
					if (group != null)
					{
						msp.buildGenerics(group);
					}
				}

				if (i == modifierCount + 2)
				{
					if (group != null)
					{
						msp.returnType = group;
					}
				}

				if (i == modifierCount + 3)
				{
					if (group != null)
					{
						msp.memberName = group;
					}
				}

				if (i == modifierCount + 4)
				{
					if (group != null)
					{
						msp.buildParamTypes(group);
					}
				}
			}
		}

		completeSignature(toParse, msp);

		return msp;
	}

	public static MemberSignatureParts fromAssembly(final String toParse) throws LogParseException
	{
		MemberSignatureParts msp = new MemberSignatureParts();

		String line = toParse.replace(S_ENTITY_APOS, S_QUOTE);

		Matcher matcher = PATTERN_ASSEMBLY_SIGNATURE.matcher(line);

		if (matcher.find())
		{
			if (DEBUG_LOGGING_ASSEMBLY)
			{
				for (int i = 0; i < matcher.groupCount(); i++)
				{
					logger.debug("part[{}] = '{}'", i, matcher.group(i));
				}
			}

			String memberName = matcher.group(2);
			String paramTypes = matcher.group(3).replace(S_OPEN_PARENTHESES, S_EMPTY).replace(S_CLOSE_PARENTHESES, S_EMPTY);
			String returnType = matcher.group(4);
			String className = matcher.group(5).replace(S_SLASH, S_DOT);

			msp.memberName = memberName;
			msp.fullyQualifiedClassName = className;

			setParamsAndReturn(msp, paramTypes, returnType);

		}

		completeSignature(toParse, msp);

		return msp;
	}

	private static void setParamsAndReturn(MemberSignatureParts msp, String paramTypes, String returnType) throws LogParseException
	{
		Class[] paramClasses = ParseUtil.getClassTypes(paramTypes);
		Class[] returnClasses = ParseUtil.getClassTypes(returnType);

		Class returnClass;

		if (returnClasses.length == 1)
		{
			returnClass = returnClasses[0];
		}
		else
		{
			returnClass = Void.class;
		}

		for (Class paramClass : paramClasses)
		{
			msp.paramTypeList.add(paramClass.getName());
		}

		msp.returnType = returnClass.getName();
	}

	private void buildGenerics(String genericsString)
	{
		String stripped = genericsString.substring(1, genericsString.length() - 1);
		String[] substitutions = stripped.split(S_COMMA);

		for (String sub : substitutions)
		{
			sub = sub.replace(S_SLASH, S_DOT); // in package names

			if (sub.contains(" extends "))
			{
				String[] pair = sub.split(" extends ");
				String child = pair[0].trim();
				String parent = pair[1].trim();
				genericsMap.put(child, parent);
			}
			else
			{
				genericsMap.put(sub, null);
			}
		}
	}

	private void buildParamTypes(String paramString)
	{
		int angleBracketDepth = 0;

		String stripped = paramString.substring(1, paramString.length() - 1);

		if (stripped.length() > 0)
		{
			StringBuilder paramBuilder = new StringBuilder();

			for (int i = 0; i < stripped.length(); i++)
			{
				char c = stripped.charAt(i);

				if (c == C_COMMA)
				{
					if (angleBracketDepth == 0)
					{
						// finished param
						addParam(paramBuilder);
					}
					else
					{
						paramBuilder.append(c);
					}
				}
				else if (c == C_OPEN_ANGLE)
				{
					angleBracketDepth++;
					paramBuilder.append(c);
				}
				else if (c == C_CLOSE_ANGLE)
				{
					angleBracketDepth--;
					paramBuilder.append(c);
				}
				else
				{
					paramBuilder.append(c);
				}
			}

			// last param
			addParam(paramBuilder);
		}

	}

	private void addParam(StringBuilder paramBuilder)
	{
		String param = paramBuilder.toString().trim();

		int lastSpacePos = param.lastIndexOf(C_SPACE);

		if (lastSpacePos != -1)
		{
			boolean first = true;
			boolean validParamName = true;

			// check every character after space to see if valid Java identifier
			for (int i = lastSpacePos + 1; i < param.length(); i++)
			{
				char c = param.charAt(i);

				if (first && !Character.isJavaIdentifierStart(c))
				{
					validParamName = false;
					break;
				}
				else if (!Character.isJavaIdentifierPart(c))
				{
					validParamName = false;
					break;
				}

				first = false;
			}

			if (validParamName)
			{
				param = param.substring(0, lastSpacePos);
			}
		}

		paramTypeList.add(param);
		paramBuilder.delete(0, paramBuilder.length());
	}

	public int getModifier()
	{
		return modifier;
	}

	public List getModifiers()
	{
		return modifierList;
	}

	public Map getGenerics()
	{
		return genericsMap;
	}

	public String getReturnType()
	{
		return returnType;
	}

	public String applyGenericSubstitutionsForClassLoading(final String typeName)
	{
		String result = typeName;

		if (typeName != null)
		{
			if (genericsMap.containsKey(typeName))
			{
				result = genericsMap.get(typeName);
			}
			else if (classBytecode != null && classBytecode.getGenericsMap().containsKey(typeName))
			{
				result = classBytecode.getGenericsMap().get(typeName);
			}
		}

		return result;
	}

	public String getMemberName()
	{
		return memberName;
	}

	public List getParamTypes()
	{
		return paramTypeList;
	}

	public String getFullyQualifiedClassName()
	{
		return fullyQualifiedClassName;
	}

	public String getPackageName()
	{
		return StringUtil.getAbbreviatedFQName(getFullyQualifiedClassName());
	}

	@Override
	public String toString()
	{
		StringBuilder sb = new StringBuilder();

		sb.append("modifiers : ");

		if (modifierList.size() > 0)
		{
			for (String mod : modifierList)
			{
				sb.append(mod).append(C_COMMA);
			}

			sb.deleteCharAt(sb.length() - 1);
		}

		sb.append(C_NEWLINE);

		sb.append("generics  : ");

		if (genericsMap.size() > 0)
		{
			for (Map.Entry entry : genericsMap.entrySet())
			{
				if (entry.getValue() != null)
				{
					sb.append(entry.getKey()).append("=>").append(entry.getValue());
				}
				else
				{
					sb.append(entry.getKey());
				}

				sb.append(C_COMMA);

			}

			sb.deleteCharAt(sb.length() - 1);
		}

		sb.append(C_NEWLINE);

		sb.append("class     : ").append(fullyQualifiedClassName).append(C_NEWLINE);

		sb.append("returnType: ").append(returnType).append(C_NEWLINE);

		sb.append("memberName: ").append(memberName).append(C_NEWLINE);

		sb.append("paramTypes: ");

		if (paramTypeList.size() > 0)
		{
			for (String param : paramTypeList)
			{
				sb.append(param).append(C_COMMA);
			}

			sb.deleteCharAt(sb.length() - 1);
		}

		return sb.toString();
	}

	public String toStringSingleLine()
	{
		StringBuilder sb = new StringBuilder();

		sb.append(fullyQualifiedClassName).append(C_DOT).append(memberName).append(S_OPEN_PARENTHESES);

		if (paramTypeList.size() > 0)
		{
			for (String param : paramTypeList)
			{
				sb.append(param).append(C_COMMA);
			}

			sb.deleteCharAt(sb.length() - 1);
		}

		sb.append(S_CLOSE_PARENTHESES);

		return sb.toString();
	}

	@Override
	public int hashCode()
	{
		final int prime = 31;
		int result = 1;
		result = prime * result + ((fullyQualifiedClassName == null) ? 0 : fullyQualifiedClassName.hashCode());
		result = prime * result + ((genericsMap == null) ? 0 : genericsMap.hashCode());
		result = prime * result + ((memberName == null) ? 0 : memberName.hashCode());
		result = prime * result + modifier;
		result = prime * result + ((modifierList == null) ? 0 : modifierList.hashCode());
		result = prime * result + ((paramTypeList == null) ? 0 : paramTypeList.hashCode());
		result = prime * result + ((returnType == null) ? 0 : returnType.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj)
	{
		if (this == obj)
		{
			return true;
		}

		if (obj == null)
		{
			return false;
		}

		if (getClass() != obj.getClass())
		{
			return false;
		}

		MemberSignatureParts other = (MemberSignatureParts) obj;

		if (fullyQualifiedClassName == null)
		{
			if (other.fullyQualifiedClassName != null)
			{
				return false;
			}
		}
		else if (!fullyQualifiedClassName.equals(other.fullyQualifiedClassName))
		{
			return false;
		}

		if (genericsMap == null)
		{
			if (other.genericsMap != null)
			{
				return false;
			}
		}
		else if (!genericsMap.equals(other.genericsMap))
		{
			return false;
		}

		if (memberName == null)
		{
			if (other.memberName != null)
			{
				return false;
			}
		}
		else if (!memberName.equals(other.memberName))
		{
			return false;
		}

		if (modifier != other.modifier)
		{
			return false;
		}

		if (modifierList == null)
		{
			if (other.modifierList != null)
			{
				return false;
			}
		}
		else if (!modifierList.equals(other.modifierList))
		{
			return false;
		}

		if (paramTypeList == null)
		{
			if (other.paramTypeList != null)
			{
				return false;
			}
		}
		else if (!paramTypeList.equals(other.paramTypeList))
		{
			return false;
		}

		if (returnType == null)
		{
			if (other.returnType != null)
			{
				return false;
			}
		}
		else if (!returnType.equals(other.returnType))
		{
			return false;
		}

		return true;
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy