Optimize DeserializedAnnotations in terms of memory traffic

Do not wrap every annotation object into an AnnotationWithTarget
This commit is contained in:
Alexander Udalov
2017-07-04 13:09:18 +03:00
parent 21197b53aa
commit 5636318eb4
5 changed files with 45 additions and 33 deletions
@@ -224,7 +224,7 @@ class MemberDeserializer(private val c: DeserializationContext) {
} }
return DeserializedAnnotationsWithPossibleTargets(c.storageManager) { return DeserializedAnnotationsWithPossibleTargets(c.storageManager) {
c.containingDeclaration.asProtoContainer()?.let { c.containingDeclaration.asProtoContainer()?.let {
c.components.annotationAndConstantLoader.loadCallableAnnotations(it, proto, kind) c.components.annotationAndConstantLoader.loadCallableAnnotations(it, proto, kind).toList()
}.orEmpty() }.orEmpty()
} }
} }
@@ -239,6 +239,7 @@ class MemberDeserializer(private val c: DeserializationContext) {
c.components.annotationAndConstantLoader c.components.annotationAndConstantLoader
.loadExtensionReceiverParameterAnnotations(it, proto, receiverTargetedKind) .loadExtensionReceiverParameterAnnotations(it, proto, receiverTargetedKind)
.map { AnnotationWithTarget(it, AnnotationUseSiteTarget.RECEIVER) } .map { AnnotationWithTarget(it, AnnotationUseSiteTarget.RECEIVER) }
.toList()
}.orEmpty() }.orEmpty()
} }
} }
@@ -255,7 +256,9 @@ class MemberDeserializer(private val c: DeserializationContext) {
val flags = if (proto.hasFlags()) proto.flags else 0 val flags = if (proto.hasFlags()) proto.flags else 0
val annotations = if (containerOfCallable != null && Flags.HAS_ANNOTATIONS.get(flags)) { val annotations = if (containerOfCallable != null && Flags.HAS_ANNOTATIONS.get(flags)) {
DeserializedAnnotations(c.storageManager) { DeserializedAnnotations(c.storageManager) {
c.components.annotationAndConstantLoader.loadValueParameterAnnotations(containerOfCallable, callable, kind, i, proto) c.components.annotationAndConstantLoader
.loadValueParameterAnnotations(containerOfCallable, callable, kind, i, proto)
.toList()
} }
} }
else Annotations.EMPTY else Annotations.EMPTY
@@ -85,9 +85,10 @@ class TypeDeserializer(
} }
val annotations = DeserializedAnnotationsWithPossibleTargets(c.storageManager) { val annotations = DeserializedAnnotationsWithPossibleTargets(c.storageManager) {
c.components.annotationAndConstantLoader c.components.annotationAndConstantLoader.loadTypeAnnotations(proto, c.nameResolver)
.loadTypeAnnotations(proto, c.nameResolver) .map { AnnotationWithTarget(it, null) }
.map { AnnotationWithTarget(it, null) } + additionalAnnotations.getAllAnnotations() .plus(additionalAnnotations.getAllAnnotations())
.toList()
} }
fun ProtoBuf.Type.collectAllArguments(): List<ProtoBuf.Type.Argument> = fun ProtoBuf.Type.collectAllArguments(): List<ProtoBuf.Type.Argument> =
@@ -16,44 +16,55 @@
package org.jetbrains.kotlin.serialization.deserialization.descriptors package org.jetbrains.kotlin.serialization.deserialization.descriptors
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationWithTarget import org.jetbrains.kotlin.descriptors.annotations.AnnotationWithTarget
import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.storage.getValue
class DeserializedAnnotations( class DeserializedAnnotations(
storageManager: StorageManager, storageManager: StorageManager,
compute: () -> List<AnnotationDescriptor> compute: () -> List<AnnotationDescriptor>
) : DeserializedAnnotationsWithPossibleTargets(
storageManager,
{ compute().map { AnnotationWithTarget(it, null) } })
open class DeserializedAnnotationsWithPossibleTargets(
storageManager: StorageManager,
compute: () -> List<AnnotationWithTarget>
) : Annotations { ) : Annotations {
private val annotations = storageManager.createLazyValue { compute().toList() } private val annotations by storageManager.createLazyValue(compute)
override fun isEmpty(): Boolean = annotations().isEmpty() override fun isEmpty(): Boolean = annotations.isEmpty()
override fun findAnnotation(fqName: FqName) = annotations().firstOrNull { override fun findAnnotation(fqName: FqName) =
annotationWithTarget -> annotations.firstOrNull { annotation -> annotation.annotationClass?.fqNameUnsafe == fqName.toUnsafe() }
if (annotationWithTarget.target != null) return@firstOrNull false
val descriptor = annotationWithTarget.annotation.annotationClass
descriptor != null && fqName.toUnsafe() == DescriptorUtils.getFqName(descriptor)
}?.annotation
override fun findExternalAnnotation(fqName: FqName) = null override fun findExternalAnnotation(fqName: FqName) = null
override fun getUseSiteTargetedAnnotations() = annotations().filter { it.target != null } override fun getUseSiteTargetedAnnotations(): List<AnnotationWithTarget> = emptyList()
override fun getAllAnnotations() = annotations() override fun getAllAnnotations(): List<AnnotationWithTarget> = annotations.map { AnnotationWithTarget(it, null) }
override fun iterator(): Iterator<AnnotationDescriptor> = annotations.iterator()
}
class DeserializedAnnotationsWithPossibleTargets(
storageManager: StorageManager,
compute: () -> List<AnnotationWithTarget>
) : Annotations {
private val annotations by storageManager.createLazyValue(compute)
override fun isEmpty(): Boolean = annotations.isEmpty()
override fun findAnnotation(fqName: FqName): AnnotationDescriptor? =
annotations.firstOrNull { (annotation, target) ->
target == null && annotation.annotationClass?.fqNameUnsafe == fqName.toUnsafe()
}?.annotation
override fun findExternalAnnotation(fqName: FqName) = null
override fun getUseSiteTargetedAnnotations(): List<AnnotationWithTarget> = annotations.filter { it.target != null }
override fun getAllAnnotations(): List<AnnotationWithTarget> = annotations
override fun iterator(): Iterator<AnnotationDescriptor> { override fun iterator(): Iterator<AnnotationDescriptor> {
return annotations().asSequence().filter { it.target == null }.map { it.annotation }.iterator() return annotations.asSequence().filter { it.target == null }.map { it.annotation }.iterator()
} }
} }
@@ -81,7 +81,7 @@ class DeserializedClassDescriptor(
Annotations.EMPTY Annotations.EMPTY
} }
else DeserializedAnnotations(c.storageManager) { else DeserializedAnnotations(c.storageManager) {
c.components.annotationAndConstantLoader.loadClassAnnotations(thisAsProtoContainer) c.components.annotationAndConstantLoader.loadClassAnnotations(thisAsProtoContainer).toList()
} }
override fun getContainingDeclaration(): DeclarationDescriptor = containingDeclaration override fun getContainingDeclaration(): DeclarationDescriptor = containingDeclaration
@@ -309,7 +309,7 @@ class DeserializedClassDescriptor(
EnumEntrySyntheticClassDescriptor.create( EnumEntrySyntheticClassDescriptor.create(
c.storageManager, this@DeserializedClassDescriptor, name, enumMemberNames, c.storageManager, this@DeserializedClassDescriptor, name, enumMemberNames,
DeserializedAnnotations(c.storageManager) { DeserializedAnnotations(c.storageManager) {
c.components.annotationAndConstantLoader.loadEnumEntryAnnotations(thisAsProtoContainer, proto) c.components.annotationAndConstantLoader.loadEnumEntryAnnotations(thisAsProtoContainer, proto).toList()
}, },
SourceElement.NO_SOURCE SourceElement.NO_SOURCE
) )
@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.serialization.deserialization.descriptors
import org.jetbrains.kotlin.descriptors.SourceElement import org.jetbrains.kotlin.descriptors.SourceElement
import org.jetbrains.kotlin.descriptors.SupertypeLoopChecker import org.jetbrains.kotlin.descriptors.SupertypeLoopChecker
import org.jetbrains.kotlin.descriptors.annotations.AnnotationWithTarget
import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.AbstractLazyTypeParameterDescriptor import org.jetbrains.kotlin.descriptors.impl.AbstractLazyTypeParameterDescriptor
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
@@ -36,10 +35,8 @@ class DeserializedTypeParameterDescriptor(
c.storageManager, c.containingDeclaration, c.nameResolver.getName(proto.name), c.storageManager, c.containingDeclaration, c.nameResolver.getName(proto.name),
Deserialization.variance(proto.variance), proto.reified, index, SourceElement.NO_SOURCE, SupertypeLoopChecker.EMPTY Deserialization.variance(proto.variance), proto.reified, index, SourceElement.NO_SOURCE, SupertypeLoopChecker.EMPTY
) { ) {
override val annotations = DeserializedAnnotationsWithPossibleTargets(c.storageManager) { override val annotations = DeserializedAnnotations(c.storageManager) {
c.components.annotationAndConstantLoader c.components.annotationAndConstantLoader.loadTypeParameterAnnotations(proto, c.nameResolver).toList()
.loadTypeParameterAnnotations(proto, c.nameResolver)
.map { AnnotationWithTarget(it, null) }
} }
override fun resolveUpperBounds(): List<KotlinType> { override fun resolveUpperBounds(): List<KotlinType> {