Don't always write JVM method signatures to metadata

When the trivial type mapping (implemented in JvmProtoBufUtil) from
ProtoBuf.Type instances works fine, don't write the signature since it can be
loaded by exactly the same trivial type mapping
This commit is contained in:
Alexander Udalov
2015-10-07 15:36:03 +03:00
parent 168f1000e4
commit 864926ee2e
12 changed files with 259 additions and 241 deletions
@@ -156,79 +156,49 @@ internal abstract class KDeclarationContainerImpl : ClassBasedDeclarationContain
}
// TODO: check resulting method's return type
fun findMethodBySignature(
signature: JvmProtoBuf.JvmMethodSignature,
nameResolver: NameResolver,
declared: Boolean
): Method? {
val name = nameResolver.getString(signature.name)
fun findMethodBySignature(name: String, desc: String, declared: Boolean): Method? {
if (name == "<init>") return null
val parameterTypes = loadParameterTypes(nameResolver, signature)
// Method for a top level function should be the one from the package facade.
// This is likely to change after the package part reform.
val owner = jClass
return owner.tryGetMethod(name, parameterTypes, declared)
return jClass.tryGetMethod(name, loadParameterTypes(desc), declared)
}
fun findDefaultMethod(
signature: JvmProtoBuf.JvmMethodSignature,
nameResolver: NameResolver,
isMember: Boolean,
declared: Boolean
): Method? {
val name = nameResolver.getString(signature.name)
fun findDefaultMethod(name: String, desc: String, isMember: Boolean, declared: Boolean): Method? {
if (name == "<init>") return null
val parameterTypes = arrayListOf<Class<*>>()
if (isMember) {
parameterTypes.add(jClass)
}
addParametersAndMasks(parameterTypes, nameResolver, signature)
addParametersAndMasks(parameterTypes, desc)
return jClass.tryGetMethod(name + JvmAbi.DEFAULT_PARAMS_IMPL_SUFFIX, parameterTypes, declared)
}
fun findConstructorBySignature(
signature: JvmProtoBuf.JvmMethodSignature,
nameResolver: NameResolver,
declared: Boolean
): Constructor<*>? {
if (nameResolver.getString(signature.name) != "<init>") return null
return jClass.tryGetConstructor(loadParameterTypes(nameResolver, signature), declared)
fun findConstructorBySignature(desc: String, declared: Boolean): Constructor<*>? {
return jClass.tryGetConstructor(loadParameterTypes(desc), declared)
}
fun findDefaultConstructor(
signature: JvmProtoBuf.JvmMethodSignature,
nameResolver: NameResolver,
declared: Boolean
): Constructor<*>? {
if (nameResolver.getString(signature.name) != "<init>") return null
fun findDefaultConstructor(desc: String, declared: Boolean): Constructor<*>? {
val parameterTypes = arrayListOf<Class<*>>()
addParametersAndMasks(parameterTypes, nameResolver, signature)
addParametersAndMasks(parameterTypes, desc)
parameterTypes.add(DEFAULT_CONSTRUCTOR_MARKER)
return jClass.tryGetConstructor(parameterTypes, declared)
}
private fun addParametersAndMasks(
result: MutableList<Class<*>>, nameResolver: NameResolver, signature: JvmProtoBuf.JvmMethodSignature
) {
val valueParameters = loadParameterTypes(nameResolver, signature)
private fun addParametersAndMasks(result: MutableList<Class<*>>, desc: String) {
val valueParameters = loadParameterTypes(desc)
result.addAll(valueParameters)
repeat((valueParameters.size() + Integer.SIZE - 1) / Integer.SIZE) {
result.add(Integer.TYPE)
}
}
private fun loadParameterTypes(nameResolver: NameResolver, signature: JvmProtoBuf.JvmMethodSignature): List<Class<*>> {
private fun loadParameterTypes(desc: String): List<Class<*>> {
val classLoader = jClass.safeClassLoader
val result = arrayListOf<Class<*>>()
val desc = nameResolver.getString(signature.desc)
var i = 1
while (desc[i] != ')') {
@@ -51,8 +51,8 @@ internal open class KFunctionImpl protected constructor(
override val caller: FunctionCaller<*> by ReflectProperties.lazySoft {
val jvmSignature = RuntimeTypeMapper.mapSignature(descriptor)
val member: Member? = when (jvmSignature) {
is KotlinConstructor -> container.findConstructorBySignature(jvmSignature.signature, jvmSignature.nameResolver, isDeclared())
is KotlinFunction -> container.findMethodBySignature(jvmSignature.signature, jvmSignature.nameResolver, isDeclared())
is KotlinConstructor -> container.findConstructorBySignature(jvmSignature.constructorDesc, isDeclared())
is KotlinFunction -> container.findMethodBySignature(jvmSignature.methodName, jvmSignature.methodDesc, isDeclared())
is JavaMethod -> jvmSignature.method
is JavaConstructor -> jvmSignature.constructor
is BuiltInFunction -> jvmSignature.getMember(container)
@@ -76,11 +76,11 @@ internal open class KFunctionImpl protected constructor(
val jvmSignature = RuntimeTypeMapper.mapSignature(descriptor)
val member: Member? = when (jvmSignature) {
is KotlinFunction -> {
container.findDefaultMethod(jvmSignature.signature, jvmSignature.nameResolver,
container.findDefaultMethod(jvmSignature.methodName, jvmSignature.methodDesc,
!Modifier.isStatic(caller.member.modifiers), isDeclared())
}
is KotlinConstructor -> {
container.findDefaultConstructor(jvmSignature.signature, jvmSignature.nameResolver, isDeclared())
container.findDefaultConstructor(jvmSignature.constructorDesc, isDeclared())
}
else -> {
// Java methods, Java constructors and built-ins don't have $default methods
@@ -116,7 +116,11 @@ private fun KPropertyImpl.Accessor<*>.computeCallerForAccessor(isGetter: Boolean
}
val accessor = accessorSignature?.let { signature ->
property.container.findMethodBySignature(signature, jvmSignature.nameResolver, Visibilities.isPrivate(descriptor.visibility))
property.container.findMethodBySignature(
jvmSignature.nameResolver.getString(signature.name),
jvmSignature.nameResolver.getString(signature.desc),
Visibilities.isPrivate(descriptor.visibility)
)
}
when {
@@ -36,6 +36,7 @@ import org.jetbrains.kotlin.serialization.deserialization.NameResolver
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPropertyDescriptor
import org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf
import org.jetbrains.kotlin.serialization.jvm.JvmProtoBufUtil
import java.lang.reflect.Constructor
import java.lang.reflect.Field
import java.lang.reflect.Member
@@ -45,22 +46,17 @@ import kotlin.reflect.KotlinReflectionInternalError
internal sealed class JvmFunctionSignature {
abstract fun asString(): String
class KotlinFunction(
val proto: ProtoBuf.Function,
val signature: JvmProtoBuf.JvmMethodSignature,
val nameResolver: NameResolver
) : JvmFunctionSignature() {
override fun asString(): String =
nameResolver.getString(signature.name) + nameResolver.getString(signature.desc)
class KotlinFunction(val signature: String) : JvmFunctionSignature() {
val methodName: String get() = signature.substringBefore('(')
val methodDesc: String get() = signature.substring(signature.indexOf('('))
override fun asString(): String = signature
}
class KotlinConstructor(
val proto: ProtoBuf.Constructor,
val signature: JvmProtoBuf.JvmMethodSignature,
val nameResolver: NameResolver
) : JvmFunctionSignature() {
override fun asString(): String =
nameResolver.getString(signature.name) + nameResolver.getString(signature.desc)
class KotlinConstructor(val signature: String) : JvmFunctionSignature() {
val constructorDesc: String get() = signature.substring(signature.indexOf('('))
override fun asString(): String = signature
}
class JavaMethod(val method: Method) : JvmFunctionSignature() {
@@ -132,19 +128,24 @@ internal object RuntimeTypeMapper {
when (function) {
is DeserializedCallableMemberDescriptor -> {
val proto = function.proto
if (proto is ProtoBuf.Function && proto.hasExtension(JvmProtoBuf.methodSignature)) {
val signature = proto.getExtension(JvmProtoBuf.methodSignature)
return JvmFunctionSignature.KotlinFunction(proto, signature, function.nameResolver)
mapIntrinsicFunctionSignature(function)?.let {
return it
}
if (proto is ProtoBuf.Constructor && proto.hasExtension(JvmProtoBuf.constructorSignature)) {
val signature = proto.getExtension(JvmProtoBuf.constructorSignature)
return JvmFunctionSignature.KotlinConstructor(proto, signature, function.nameResolver)
val proto = function.proto
if (proto is ProtoBuf.Function) {
JvmProtoBufUtil.getJvmMethodSignature(proto, function.nameResolver)?.let { signature ->
return JvmFunctionSignature.KotlinFunction(signature)
}
}
if (proto is ProtoBuf.Constructor) {
JvmProtoBufUtil.getJvmConstructorSignature(proto, function.nameResolver)?.let { signature ->
return JvmFunctionSignature.KotlinConstructor(signature)
}
}
// If it's a deserialized function but has no JVM signature, it must be from built-ins
return mapIntrinsicFunctionSignature(function) ?:
throw KotlinReflectionInternalError("Reflection on built-in Kotlin types is not yet fully supported. " +
"No metadata found for $function")
throw KotlinReflectionInternalError("Reflection on built-in Kotlin types is not yet fully supported. " +
"No metadata found for $function")
}
is JavaMethodDescriptor -> {
val method = ((function.source as? JavaSourceElement)?.javaElement as? ReflectJavaMethod)?.member ?: