Simplify storage of JVM signatures in binary metadata
Store the whole method & field descriptor strings. Moving these strings to separate annotation arguments later will allow to reuse them with the ones in the constant pool, presumably allowing to save lots of space (up to 10%)
This commit is contained in:
@@ -22,39 +22,18 @@ import "core/deserialization/src/descriptors.proto";
|
||||
option java_outer_classname = "JvmProtoBuf";
|
||||
option optimize_for = LITE_RUNTIME;
|
||||
|
||||
message JvmType {
|
||||
// Either a primitive type, or a class FQ name should be present
|
||||
|
||||
enum PrimitiveType {
|
||||
// These values correspond to ASM Type sorts
|
||||
VOID = 0;
|
||||
BOOLEAN = 1;
|
||||
CHAR = 2;
|
||||
BYTE = 3;
|
||||
SHORT = 4;
|
||||
INT = 5;
|
||||
FLOAT = 6;
|
||||
LONG = 7;
|
||||
DOUBLE = 8;
|
||||
}
|
||||
|
||||
optional PrimitiveType primitive_type = 1;
|
||||
|
||||
// id in QualifiedNameTable of a name in the following format: 'package.Outer$Nested'
|
||||
optional int32 class_fq_name = 2 [(fq_name_id_in_table) = true];
|
||||
|
||||
optional int32 array_dimension = 3 [default = 0];
|
||||
}
|
||||
|
||||
message JvmMethodSignature {
|
||||
required int32 name = 1 [(string_id_in_table) = true];
|
||||
required JvmType return_type = 2;
|
||||
repeated JvmType parameter_type = 3;
|
||||
|
||||
// JVM descriptor of the method, e.g. '(Ljava/util/List;)[Ljava/lang/Object;'
|
||||
required int32 desc = 2 [(string_id_in_table) = true];
|
||||
}
|
||||
|
||||
message JvmFieldSignature {
|
||||
required int32 name = 1 [(string_id_in_table) = true];
|
||||
required JvmType type = 2;
|
||||
|
||||
// JVM descriptor of the field type, e.g. 'Ljava/lang/String;'
|
||||
required int32 desc = 2 [(string_id_in_table) = true];
|
||||
|
||||
// True iff this field is a backing field for a companion object and is really present as a static
|
||||
// field in the outer class, not as an instance field here
|
||||
@@ -62,11 +41,9 @@ message JvmFieldSignature {
|
||||
}
|
||||
|
||||
message JvmPropertySignature {
|
||||
// A property itself is identified either by the field, or by the synthetic method.
|
||||
// If the property is annotated, then either field or synthetic_method should be present
|
||||
optional JvmFieldSignature field = 1;
|
||||
|
||||
// Annotations on properties without backing fields are written on a synthetic method with this signature
|
||||
// Annotations on properties are written on a synthetic method with this signature
|
||||
optional JvmMethodSignature synthetic_method = 2;
|
||||
|
||||
optional JvmMethodSignature getter = 3;
|
||||
|
||||
+14
-17
@@ -243,11 +243,11 @@ public abstract class AbstractBinaryClassAnnotationAndConstantLoader<A : Any, C
|
||||
|
||||
kotlinClass.visitMembers(object : KotlinJvmBinaryClass.MemberVisitor {
|
||||
override fun visitMethod(name: Name, desc: String): KotlinJvmBinaryClass.MethodAnnotationVisitor? {
|
||||
return AnnotationVisitorForMethod(MemberSignature.fromMethodNameAndDesc(name.asString() + desc))
|
||||
return AnnotationVisitorForMethod(MemberSignature.fromMethodNameAndDesc(name.asString(), desc))
|
||||
}
|
||||
|
||||
override fun visitField(name: Name, desc: String, initializer: Any?): KotlinJvmBinaryClass.AnnotationVisitor? {
|
||||
val signature = MemberSignature.fromFieldNameAndDesc(name, desc)
|
||||
val signature = MemberSignature.fromFieldNameAndDesc(name.asString(), desc)
|
||||
|
||||
if (initializer != null) {
|
||||
val constant = loadConstant(desc, initializer)
|
||||
@@ -299,17 +299,16 @@ public abstract class AbstractBinaryClassAnnotationAndConstantLoader<A : Any, C
|
||||
): MemberSignature? {
|
||||
if (!proto.hasExtension(propertySignature)) return null
|
||||
|
||||
val propertySignature = proto.getExtension(propertySignature)
|
||||
val deserializer = SignatureDeserializer(nameResolver)
|
||||
val signature = proto.getExtension(propertySignature)
|
||||
|
||||
if (field && propertySignature.hasField()) {
|
||||
val field = propertySignature.field
|
||||
val type = deserializer.typeDescriptor(field.type)
|
||||
val name = nameResolver.getName(field.name)
|
||||
return MemberSignature.fromFieldNameAndDesc(name, type)
|
||||
if (field && signature.hasField()) {
|
||||
return MemberSignature.fromFieldNameAndDesc(
|
||||
nameResolver.getString(signature.field.name),
|
||||
nameResolver.getString(signature.field.desc)
|
||||
)
|
||||
}
|
||||
else if (synthetic && propertySignature.hasSyntheticMethod()) {
|
||||
return deserializer.methodSignature(propertySignature.syntheticMethod)
|
||||
else if (synthetic && signature.hasSyntheticMethod()) {
|
||||
return MemberSignature.fromMethod(nameResolver, signature.syntheticMethod)
|
||||
}
|
||||
|
||||
return null
|
||||
@@ -320,17 +319,15 @@ public abstract class AbstractBinaryClassAnnotationAndConstantLoader<A : Any, C
|
||||
nameResolver: NameResolver,
|
||||
kind: AnnotatedCallableKind
|
||||
): MemberSignature? {
|
||||
val deserializer = SignatureDeserializer(nameResolver)
|
||||
|
||||
when (kind) {
|
||||
AnnotatedCallableKind.FUNCTION -> if (proto.hasExtension(methodSignature)) {
|
||||
return deserializer.methodSignature(proto.getExtension(methodSignature))
|
||||
return MemberSignature.fromMethod(nameResolver, proto.getExtension(methodSignature))
|
||||
}
|
||||
AnnotatedCallableKind.PROPERTY_GETTER -> if (proto.hasExtension(propertySignature)) {
|
||||
return deserializer.methodSignature(proto.getExtension(propertySignature).getGetter())
|
||||
return MemberSignature.fromMethod(nameResolver, proto.getExtension(propertySignature).getter)
|
||||
}
|
||||
AnnotatedCallableKind.PROPERTY_SETTER -> if (proto.hasExtension(propertySignature)) {
|
||||
return deserializer.methodSignature(proto.getExtension(propertySignature).getSetter())
|
||||
return MemberSignature.fromMethod(nameResolver, proto.getExtension(propertySignature).setter)
|
||||
}
|
||||
AnnotatedCallableKind.PROPERTY -> return getPropertySignature(proto, nameResolver, true, true)
|
||||
}
|
||||
@@ -341,4 +338,4 @@ public abstract class AbstractBinaryClassAnnotationAndConstantLoader<A : Any, C
|
||||
public val memberAnnotations: Map<MemberSignature, List<A>>,
|
||||
public val propertyConstants: Map<MemberSignature, C>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+11
-5
@@ -16,20 +16,26 @@
|
||||
|
||||
package org.jetbrains.kotlin.load.kotlin
|
||||
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.serialization.deserialization.NameResolver
|
||||
import org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf
|
||||
|
||||
// The purpose of this class is to hold a unique signature of either a method or a field, so that annotations on a member can be put
|
||||
// into a map indexed by these signatures
|
||||
data class MemberSignature private constructor(private val signature: String) {
|
||||
companion object {
|
||||
@JvmStatic
|
||||
public fun fromMethodNameAndDesc(nameAndDesc: String): MemberSignature {
|
||||
return MemberSignature(nameAndDesc)
|
||||
public fun fromMethod(nameResolver: NameResolver, signature: JvmProtoBuf.JvmMethodSignature): MemberSignature {
|
||||
return fromMethodNameAndDesc(nameResolver.getString(signature.name), nameResolver.getString(signature.desc))
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
public fun fromFieldNameAndDesc(name: Name, desc: String): MemberSignature {
|
||||
return MemberSignature(name.asString() + "#" + desc)
|
||||
public fun fromMethodNameAndDesc(name: String, desc: String): MemberSignature {
|
||||
return MemberSignature(name + desc)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
public fun fromFieldNameAndDesc(name: String, desc: String): MemberSignature {
|
||||
return MemberSignature(name + "#" + desc)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
|
||||
-82
@@ -1,82 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.load.kotlin;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf;
|
||||
import org.jetbrains.kotlin.serialization.deserialization.NameResolver;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
|
||||
public class SignatureDeserializer {
|
||||
// These types are ordered according to their sorts, this is significant for deserialization
|
||||
private static final char[] PRIMITIVE_TYPES = new char[] {'V', 'Z', 'C', 'B', 'S', 'I', 'F', 'J', 'D'};
|
||||
|
||||
private final NameResolver nameResolver;
|
||||
|
||||
public SignatureDeserializer(@NotNull NameResolver nameResolver) {
|
||||
this.nameResolver = nameResolver;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String methodSignatureString(@NotNull JvmProtoBuf.JvmMethodSignature signature) {
|
||||
Name name = nameResolver.getName(signature.getName());
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append('(');
|
||||
for (int i = 0, length = signature.getParameterTypeCount(); i < length; i++) {
|
||||
typeDescriptor(signature.getParameterType(i), sb);
|
||||
}
|
||||
sb.append(')');
|
||||
typeDescriptor(signature.getReturnType(), sb);
|
||||
|
||||
return name.asString() + sb.toString();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public MemberSignature methodSignature(@NotNull JvmProtoBuf.JvmMethodSignature signature) {
|
||||
return MemberSignature.fromMethodNameAndDesc(methodSignatureString(signature));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String typeDescriptor(@NotNull JvmProtoBuf.JvmType type) {
|
||||
return typeDescriptor(type, new StringBuilder()).toString();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private StringBuilder typeDescriptor(@NotNull JvmProtoBuf.JvmType type, @NotNull StringBuilder sb) {
|
||||
for (int i = 0; i < type.getArrayDimension(); i++) {
|
||||
sb.append('[');
|
||||
}
|
||||
|
||||
if (type.hasPrimitiveType()) {
|
||||
sb.append(PRIMITIVE_TYPES[type.getPrimitiveType().ordinal()]);
|
||||
}
|
||||
else {
|
||||
sb.append("L");
|
||||
sb.append(fqNameToInternalName(nameResolver.getFqName(type.getClassFqName())));
|
||||
sb.append(";");
|
||||
}
|
||||
|
||||
return sb;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String fqNameToInternalName(@NotNull FqName fqName) {
|
||||
return fqName.asString().replace('.', '/');
|
||||
}
|
||||
}
|
||||
+88
-1091
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user