Parcelable: Migrate to canonical NEW-DUP-INVOKESPECIAL form (KT-20545)

This commit is contained in:
Yan Zhulanow
2017-11-15 14:36:11 +09:00
parent 37543deefa
commit 2819fc718a
7 changed files with 87 additions and 73 deletions
@@ -75,11 +75,6 @@ class UninitializedStoresProcessor(
private val methodNode: MethodNode, private val methodNode: MethodNode,
private val shouldPreserveClassInitialization: Boolean private val shouldPreserveClassInitialization: Boolean
) { ) {
companion object {
val AVOID_UNINITIALIZED_OBJECT_COPYING_CHECK_ANNOTATION_DESCRIPTOR =
"Lkotlin/internal/annotations/AvoidUninitializedObjectCopyingCheck;"
}
// <init> method is "special", because it will invoke <init> from this class or from a base class for #0 // <init> method is "special", because it will invoke <init> from this class or from a base class for #0
// //
// <clinit> method is "special", because <clinit> for singleton objects is generated as: // <clinit> method is "special", because <clinit> for singleton objects is generated as:
@@ -88,11 +83,7 @@ class UninitializedStoresProcessor(
// and the newly created value is dropped. // and the newly created value is dropped.
private val isInSpecialMethod = methodNode.name == "<init>" || methodNode.name == "<clinit>" private val isInSpecialMethod = methodNode.name == "<init>" || methodNode.name == "<clinit>"
private val shouldCheckUninitializedObjectCopy = !methodNode.invisibleAnnotations.orEmpty()
.any { it.desc == AVOID_UNINITIALIZED_OBJECT_COPYING_CHECK_ANNOTATION_DESCRIPTOR }
fun run() { fun run() {
if (!shouldCheckUninitializedObjectCopy) return
val interpreter = UninitializedNewValueMarkerInterpreter(methodNode.instructions) val interpreter = UninitializedNewValueMarkerInterpreter(methodNode.instructions)
val frames = CustomFramesMethodAnalyzer( val frames = CustomFramesMethodAnalyzer(
@@ -183,7 +174,7 @@ class UninitializedStoresProcessor(
assert(insn.opcode == Opcodes.INVOKESPECIAL) { "Expected opcode Opcodes.INVOKESPECIAL for <init>, but ${insn.opcode} found" } assert(insn.opcode == Opcodes.INVOKESPECIAL) { "Expected opcode Opcodes.INVOKESPECIAL for <init>, but ${insn.opcode} found" }
val paramsCountIncludingReceiver = Type.getArgumentTypes((insn as MethodInsnNode).desc).size + 1 val paramsCountIncludingReceiver = Type.getArgumentTypes((insn as MethodInsnNode).desc).size + 1
val newValue = peek(paramsCountIncludingReceiver) as? UninitializedNewValue ?: val newValue = peek(paramsCountIncludingReceiver) as? UninitializedNewValue ?:
if (isInSpecialMethod || !shouldCheckUninitializedObjectCopy) if (isInSpecialMethod)
return null return null
else else
error("Expected value generated with NEW") error("Expected value generated with NEW")
@@ -18,36 +18,34 @@ package org.jetbrains.kotlin.android.parcel
import kotlinx.android.parcel.TypeParceler import kotlinx.android.parcel.TypeParceler
import org.jetbrains.kotlin.android.parcel.ParcelableResolveExtension.Companion.createMethod import org.jetbrains.kotlin.android.parcel.ParcelableResolveExtension.Companion.createMethod
import org.jetbrains.kotlin.android.parcel.serializers.*
import org.jetbrains.kotlin.android.parcel.ParcelableSyntheticComponent.ComponentKind.* import org.jetbrains.kotlin.android.parcel.ParcelableSyntheticComponent.ComponentKind.*
import org.jetbrains.kotlin.android.parcel.serializers.PARCEL_TYPE
import org.jetbrains.kotlin.android.parcel.serializers.ParcelSerializer
import org.jetbrains.kotlin.android.parcel.serializers.TypeParcelerMapping
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.kotlin.codegen.ExpressionCodegen import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.FunctionGenerationStrategy.CodegenBased import org.jetbrains.kotlin.codegen.FunctionGenerationStrategy.CodegenBased
import org.jetbrains.kotlin.codegen.ImplementationBodyCodegen import org.jetbrains.kotlin.codegen.ImplementationBodyCodegen
import org.jetbrains.kotlin.codegen.OwnerKind import org.jetbrains.kotlin.codegen.OwnerKind
import org.jetbrains.kotlin.codegen.context.ClassContext import org.jetbrains.kotlin.codegen.context.ClassContext
import org.jetbrains.kotlin.codegen.coroutines.UninitializedStoresProcessor
import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension
import org.jetbrains.kotlin.codegen.writeSyntheticClassMetadata import org.jetbrains.kotlin.codegen.writeSyntheticClassMetadata
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl
import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.incremental.components.NoLookupLocation.WHEN_GET_ALL_DESCRIPTORS import org.jetbrains.kotlin.incremental.components.NoLookupLocation.WHEN_GET_ALL_DESCRIPTORS
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorFactory import org.jetbrains.kotlin.resolve.DescriptorFactory
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.TypeUtils
@@ -104,8 +102,6 @@ open class ParcelableCodegenExtension : ExpressionCodegenExtension {
val containerAsmType = codegen.typeMapper.mapType(this.defaultType) val containerAsmType = codegen.typeMapper.mapType(this.defaultType)
return findFunction(WRITE_TO_PARCEL)?.write(codegen) { return findFunction(WRITE_TO_PARCEL)?.write(codegen) {
v.visitAnnotation(UninitializedStoresProcessor.AVOID_UNINITIALIZED_OBJECT_COPYING_CHECK_ANNOTATION_DESCRIPTOR, false)
if (parcelerObject != null) { if (parcelerObject != null) {
val (companionAsmType, companionFieldName) = getCompanionClassType(containerAsmType, parcelerObject) val (companionAsmType, companionFieldName) = getCompanionClassType(containerAsmType, parcelerObject)
@@ -117,7 +113,13 @@ open class ParcelableCodegenExtension : ExpressionCodegenExtension {
"(${containerAsmType.descriptor}${PARCEL_TYPE.descriptor}I)V", false) "(${containerAsmType.descriptor}${PARCEL_TYPE.descriptor}I)V", false)
} }
else { else {
val globalContext = ParcelSerializer.ParcelSerializerContext(codegen.typeMapper, containerAsmType, emptyList()) val frameMap = FrameMap().apply {
enterTemp(containerAsmType)
enterTemp(PARCEL_TYPE)
enterTemp(Type.INT_TYPE)
}
val globalContext = ParcelSerializer.ParcelSerializerContext(codegen.typeMapper, containerAsmType, emptyList(), frameMap)
for ((fieldName, type, parcelers) in properties) { for ((fieldName, type, parcelers) in properties) {
val asmType = codegen.typeMapper.mapType(type) val asmType = codegen.typeMapper.mapType(type)
@@ -188,10 +190,9 @@ open class ParcelableCodegenExtension : ExpressionCodegenExtension {
properties: List<PropertyToSerialize> properties: List<PropertyToSerialize>
) { ) {
val containerAsmType = codegen.typeMapper.mapType(parcelableClass) val containerAsmType = codegen.typeMapper.mapType(parcelableClass)
val creatorAsmType = codegen.typeMapper.mapType(creatorClass)
createMethod(creatorClass, CREATE_FROM_PARCEL, parcelableClass.builtIns.anyType, "in" to parcelClassType).write(codegen) { createMethod(creatorClass, CREATE_FROM_PARCEL, parcelableClass.builtIns.anyType, "in" to parcelClassType).write(codegen) {
v.visitAnnotation(UninitializedStoresProcessor.AVOID_UNINITIALIZED_OBJECT_COPYING_CHECK_ANNOTATION_DESCRIPTOR, false)
if (parcelerObject != null) { if (parcelerObject != null) {
val (companionAsmType, companionFieldName) = getCompanionClassType(containerAsmType, parcelerObject) val (companionAsmType, companionFieldName) = getCompanionClassType(containerAsmType, parcelerObject)
@@ -204,7 +205,12 @@ open class ParcelableCodegenExtension : ExpressionCodegenExtension {
v.dup() v.dup()
val asmConstructorParameters = StringBuilder() val asmConstructorParameters = StringBuilder()
val globalContext = ParcelSerializer.ParcelSerializerContext(codegen.typeMapper, containerAsmType, emptyList()) val frameMap = FrameMap().apply {
enterTemp(creatorAsmType)
enterTemp(PARCEL_TYPE)
}
val globalContext = ParcelSerializer.ParcelSerializerContext(codegen.typeMapper, containerAsmType, emptyList(), frameMap)
for ((_, type, parcelers) in properties) { for ((_, type, parcelers) in properties) {
val asmType = codegen.typeMapper.mapType(type) val asmType = codegen.typeMapper.mapType(type)
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.android.parcel.serializers.isParcelable
import org.jetbrains.kotlin.android.synthetic.diagnostic.DefaultErrorMessagesAndroid import org.jetbrains.kotlin.android.synthetic.diagnostic.DefaultErrorMessagesAndroid
import org.jetbrains.kotlin.android.synthetic.diagnostic.ErrorsAndroid import org.jetbrains.kotlin.android.synthetic.diagnostic.ErrorsAndroid
import org.jetbrains.kotlin.codegen.ClassBuilderMode import org.jetbrains.kotlin.codegen.ClassBuilderMode
import org.jetbrains.kotlin.codegen.FrameMap
import org.jetbrains.kotlin.codegen.state.IncompatibleClassTracker import org.jetbrains.kotlin.codegen.state.IncompatibleClassTracker
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
@@ -214,7 +215,12 @@ class ParcelableDeclarationChecker : SimpleDeclarationChecker {
try { try {
val parcelers = getTypeParcelers(descriptor.annotations) + getTypeParcelers(containerClass.annotations) val parcelers = getTypeParcelers(descriptor.annotations) + getTypeParcelers(containerClass.annotations)
val context = ParcelSerializer.ParcelSerializerContext(typeMapper, typeMapper.mapType(containerClass.defaultType), parcelers) val context = ParcelSerializer.ParcelSerializerContext(
typeMapper,
typeMapper.mapType(containerClass.defaultType),
parcelers,
FrameMap())
ParcelSerializer.get(type, asmType, context, strict = true) ParcelSerializer.get(type, asmType, context, strict = true)
} }
catch (e: IllegalArgumentException) { catch (e: IllegalArgumentException) {
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.android.parcel.serializers
import kotlinx.android.parcel.WriteWith import kotlinx.android.parcel.WriteWith
import org.jetbrains.kotlin.android.parcel.isParcelize import org.jetbrains.kotlin.android.parcel.isParcelize
import org.jetbrains.kotlin.codegen.FrameMap
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.ClassKind
@@ -54,7 +55,8 @@ interface ParcelSerializer {
data class ParcelSerializerContext( data class ParcelSerializerContext(
val typeMapper: KotlinTypeMapper, val typeMapper: KotlinTypeMapper,
val containerClassType: Type, val containerClassType: Type,
val typeParcelers: List<TypeParcelerMapping> val typeParcelers: List<TypeParcelerMapping>,
val frameMap: FrameMap
) { ) {
fun findParcelerClass(type: KotlinType): KotlinType? { fun findParcelerClass(type: KotlinType): KotlinType? {
return typeParcelers.firstOrNull { it.first == type }?.second return typeParcelers.firstOrNull { it.first == type }?.second
@@ -152,7 +154,7 @@ interface ParcelSerializer {
} }
val elementSerializer = get(elementType, elementAsmType, context, forceBoxed = true, strict = strict()) val elementSerializer = get(elementType, elementAsmType, context, forceBoxed = true, strict = strict())
wrapToNullAwareIfNeeded(type, ListSetParcelSerializer(asmType, elementSerializer)) wrapToNullAwareIfNeeded(type, ListSetParcelSerializer(asmType, elementSerializer, context.frameMap))
} }
className == Map::class.java.canonicalName className == Map::class.java.canonicalName
@@ -168,7 +170,7 @@ interface ParcelSerializer {
keyType.type, typeMapper.mapTypeSafe(keyType.type, forceBoxed = true), context, forceBoxed = true, strict = strict()) keyType.type, typeMapper.mapTypeSafe(keyType.type, forceBoxed = true), context, forceBoxed = true, strict = strict())
val valueSerializer = get( val valueSerializer = get(
valueType.type, typeMapper.mapTypeSafe(valueType.type, forceBoxed = true), context, forceBoxed = true, strict = strict()) valueType.type, typeMapper.mapTypeSafe(valueType.type, forceBoxed = true), context, forceBoxed = true, strict = strict())
wrapToNullAwareIfNeeded(type, MapParcelSerializer(asmType, keySerializer, valueSerializer)) wrapToNullAwareIfNeeded(type, MapParcelSerializer(asmType, keySerializer, valueSerializer, context.frameMap))
} }
asmType.isBoxedPrimitive() -> wrapToNullAwareIfNeeded(type, BoxedPrimitiveTypeParcelSerializer.forBoxedType(asmType)) asmType.isBoxedPrimitive() -> wrapToNullAwareIfNeeded(type, BoxedPrimitiveTypeParcelSerializer.forBoxedType(asmType))
@@ -206,16 +208,16 @@ interface ParcelSerializer {
Method("readSparseBooleanArray")) Method("readSparseBooleanArray"))
asmType.isSparseIntArray() -> wrapToNullAwareIfNeeded(type, SparseArrayParcelSerializer( asmType.isSparseIntArray() -> wrapToNullAwareIfNeeded(type, SparseArrayParcelSerializer(
asmType, PrimitiveTypeParcelSerializer.getInstance(Type.INT_TYPE))) asmType, PrimitiveTypeParcelSerializer.getInstance(Type.INT_TYPE), context.frameMap))
asmType.isSparseLongArray() -> wrapToNullAwareIfNeeded(type, SparseArrayParcelSerializer( asmType.isSparseLongArray() -> wrapToNullAwareIfNeeded(type, SparseArrayParcelSerializer(
asmType, PrimitiveTypeParcelSerializer.getInstance(Type.LONG_TYPE))) asmType, PrimitiveTypeParcelSerializer.getInstance(Type.LONG_TYPE), context.frameMap))
asmType.isSparseArray() -> { asmType.isSparseArray() -> {
val elementType = type.arguments.single().type val elementType = type.arguments.single().type
val elementSerializer = get( val elementSerializer = get(
elementType, typeMapper.mapTypeSafe(elementType, forceBoxed = true), context, forceBoxed = true, strict = strict()) elementType, typeMapper.mapTypeSafe(elementType, forceBoxed = true), context, forceBoxed = true, strict = strict())
wrapToNullAwareIfNeeded(type, SparseArrayParcelSerializer(asmType, elementSerializer)) wrapToNullAwareIfNeeded(type, SparseArrayParcelSerializer(asmType, elementSerializer, context.frameMap))
} }
type.isCharSequence() -> CharSequenceParcelSerializer(asmType) type.isCharSequence() -> CharSequenceParcelSerializer(asmType)
@@ -19,9 +19,10 @@ package org.jetbrains.kotlin.android.parcel.serializers
import kotlinx.android.parcel.Parceler import kotlinx.android.parcel.Parceler
import org.jetbrains.kotlin.android.parcel.serializers.BoxedPrimitiveTypeParcelSerializer.Companion.BOXED_VALUE_METHOD_NAMES import org.jetbrains.kotlin.android.parcel.serializers.BoxedPrimitiveTypeParcelSerializer.Companion.BOXED_VALUE_METHOD_NAMES
import org.jetbrains.kotlin.codegen.AsmUtil import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.FrameMap
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.codegen.useTmpVar
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.org.objectweb.asm.Label import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Type import org.jetbrains.org.objectweb.asm.Type
@@ -186,8 +187,9 @@ internal fun InstructionAdapter.castIfNeeded(targetType: Type) {
internal class ListSetParcelSerializer( internal class ListSetParcelSerializer(
asmType: Type, asmType: Type,
elementSerializer: ParcelSerializer elementSerializer: ParcelSerializer,
) : AbstractCollectionParcelSerializer(asmType, elementSerializer) { frameMap: FrameMap
) : AbstractCollectionParcelSerializer(asmType, elementSerializer, frameMap) {
override fun getSize(v: InstructionAdapter) { override fun getSize(v: InstructionAdapter) {
v.invokeinterface("java/util/Collection", "size", "()I") v.invokeinterface("java/util/Collection", "size", "()I")
} }
@@ -216,8 +218,9 @@ internal class ListSetParcelSerializer(
internal class MapParcelSerializer( internal class MapParcelSerializer(
asmType: Type, asmType: Type,
private val keySerializer: ParcelSerializer, private val keySerializer: ParcelSerializer,
elementSerializer: ParcelSerializer elementSerializer: ParcelSerializer,
) : AbstractCollectionParcelSerializer(asmType, elementSerializer) { frameMap: FrameMap
) : AbstractCollectionParcelSerializer(asmType, elementSerializer, frameMap) {
override fun getSize(v: InstructionAdapter) { override fun getSize(v: InstructionAdapter) {
v.invokeinterface("java/util/Map", "size", "()I") v.invokeinterface("java/util/Map", "size", "()I")
} }
@@ -260,7 +263,8 @@ internal class MapParcelSerializer(
abstract internal class AbstractCollectionParcelSerializer( abstract internal class AbstractCollectionParcelSerializer(
final override val asmType: Type, final override val asmType: Type,
protected val elementSerializer: ParcelSerializer protected val elementSerializer: ParcelSerializer,
private val frameMap: FrameMap
) : ParcelSerializer { ) : ParcelSerializer {
protected val collectionType: Type = Type.getObjectType(when (asmType.internalName) { protected val collectionType: Type = Type.getObjectType(when (asmType.internalName) {
"java/util/List" -> "java/util/ArrayList" "java/util/List" -> "java/util/ArrayList"
@@ -331,27 +335,27 @@ abstract internal class AbstractCollectionParcelSerializer(
} }
override fun readValue(v: InstructionAdapter) { override fun readValue(v: InstructionAdapter) {
frameMap.useTmpVar(Type.INT_TYPE) { sizeVarIndex ->
v.invokevirtual(PARCEL_TYPE.internalName, "readInt", "()I", false) // -> size
v.store(sizeVarIndex, Type.INT_TYPE)
v.anew(collectionType) // -> list
v.dup() // -> list, list
if (hasConstructorWithCapacity) {
v.load(sizeVarIndex, Type.INT_TYPE)
v.invokespecial(collectionType.internalName, "<init>", "(I)V", false) // -> list
} else {
v.invokespecial(collectionType.internalName, "<init>", "()V", false) // -> list
}
v.load(sizeVarIndex, Type.INT_TYPE) // -> list, size
}
val nextLoopIteration = Label() val nextLoopIteration = Label()
val loopIsOver = Label() val loopIsOver = Label()
// Read list size
v.invokevirtual(PARCEL_TYPE.internalName, "readInt", "()I", false) // -> size
v.dup() // -> size, size
v.anew(collectionType) // -> size, size, list
v.dupX1() // -> size, list, size, list
v.swap() // -> size, list, list, size
if (hasConstructorWithCapacity) {
v.invokespecial(collectionType.internalName, "<init>", "(I)V", false) // -> size, list
}
else {
v.pop() // -> size, list, list
v.invokespecial(collectionType.internalName, "<init>", "()V", false) // -> size, list
}
v.visitLabel(nextLoopIteration) v.visitLabel(nextLoopIteration)
v.swap() // -> list, size
v.dupX1() // -> size, list, size v.dupX1() // -> size, list, size
v.ifeq(loopIsOver) // -> size, list v.ifeq(loopIsOver) // -> size, list
v.dup() // -> size, list, list v.dup() // -> size, list, list
@@ -362,16 +366,19 @@ abstract internal class AbstractCollectionParcelSerializer(
v.aconst(-1) // -> list, size, (-1) v.aconst(-1) // -> list, size, (-1)
v.add(Type.INT_TYPE) // -> list, (size - 1) v.add(Type.INT_TYPE) // -> list, (size - 1)
v.swap() // -> size, list
v.goTo(nextLoopIteration) v.goTo(nextLoopIteration)
v.visitLabel(loopIsOver) v.visitLabel(loopIsOver)
v.swap() v.swap() // -> list, size
v.pop() v.pop()
} }
} }
internal class SparseArrayParcelSerializer(override val asmType: Type, private val valueSerializer: ParcelSerializer) : ParcelSerializer { internal class SparseArrayParcelSerializer(
override val asmType: Type,
private val valueSerializer: ParcelSerializer,
private val frameMap: FrameMap
) : ParcelSerializer {
private val valueType = (valueSerializer as? PrimitiveTypeParcelSerializer)?.asmType ?: Type.getObjectType("java/lang/Object") private val valueType = (valueSerializer as? PrimitiveTypeParcelSerializer)?.asmType ?: Type.getObjectType("java/lang/Object")
override fun writeValue(v: InstructionAdapter) { override fun writeValue(v: InstructionAdapter) {
@@ -421,12 +428,17 @@ internal class SparseArrayParcelSerializer(override val asmType: Type, private v
} }
override fun readValue(v: InstructionAdapter) { override fun readValue(v: InstructionAdapter) {
v.invokevirtual(PARCEL_TYPE.internalName, "readInt", "()I", false) // -> size frameMap.useTmpVar(Type.INT_TYPE) { sizeVarIndex ->
v.dup() // -> size, size v.invokevirtual(PARCEL_TYPE.internalName, "readInt", "()I", false) // -> size
v.anew(asmType) // -> size, size, arr v.store(sizeVarIndex, Type.INT_TYPE) // -> (empty)
v.dupX2() // -> arr, size, size, arr
v.swap() // -> arr, size, arr, size v.anew(asmType) // -> arr
v.invokespecial(asmType.internalName, "<init>", "(I)V", false) // -> arr, size v.dup() // -> arr, arr
v.load(sizeVarIndex, Type.INT_TYPE) // -> arr, arr, size
v.invokespecial(asmType.internalName, "<init>", "(I)V", false) // -> arr
v.load(sizeVarIndex, Type.INT_TYPE) // -> arr, size
}
val nextLoopIteration = Label() val nextLoopIteration = Label()
val loopIsOver = Label() val loopIsOver = Label()
@@ -18,13 +18,13 @@ public final class User$Creator : java/lang/Object, android/os/Parcelable$Creato
CHECKCAST CHECKCAST
ALOAD (1) ALOAD (1)
INVOKEVIRTUAL (android/os/Parcel, readInt, ()I) INVOKEVIRTUAL (android/os/Parcel, readInt, ()I)
DUP ISTORE (2)
NEW NEW
DUP_X1 DUP
SWAP ILOAD (2)
INVOKESPECIAL (java/util/ArrayList, <init>, (I)V) INVOKESPECIAL (java/util/ArrayList, <init>, (I)V)
ILOAD (2)
LABEL (L2) LABEL (L2)
SWAP
DUP_X1 DUP_X1
IFEQ (L3) IFEQ (L3)
DUP DUP
@@ -35,7 +35,6 @@ public final class User$Creator : java/lang/Object, android/os/Parcelable$Creato
SWAP SWAP
LDC (-1) LDC (-1)
IADD IADD
SWAP
GOTO (L2) GOTO (L2)
LABEL (L3) LABEL (L3)
SWAP SWAP
@@ -75,8 +75,6 @@ class KaptJavaLog(
} }
override fun report(diagnostic: JCDiagnostic) { override fun report(diagnostic: JCDiagnostic) {
System.err.println("Diagnostic code: ${diagnostic.code}")
if (diagnostic.type == JCDiagnostic.DiagnosticType.ERROR && diagnostic.code in IGNORED_DIAGNOSTICS) { if (diagnostic.type == JCDiagnostic.DiagnosticType.ERROR && diagnostic.code in IGNORED_DIAGNOSTICS) {
return return
} }