diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/processUninitializedStores.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/processUninitializedStores.kt index ed42bb30407..45f27bef086 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/processUninitializedStores.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/processUninitializedStores.kt @@ -75,11 +75,6 @@ class UninitializedStoresProcessor( private val methodNode: MethodNode, private val shouldPreserveClassInitialization: Boolean ) { - companion object { - val AVOID_UNINITIALIZED_OBJECT_COPYING_CHECK_ANNOTATION_DESCRIPTOR = - "Lkotlin/internal/annotations/AvoidUninitializedObjectCopyingCheck;" - } - // method is "special", because it will invoke from this class or from a base class for #0 // // method is "special", because for singleton objects is generated as: @@ -88,11 +83,7 @@ class UninitializedStoresProcessor( // and the newly created value is dropped. private val isInSpecialMethod = methodNode.name == "" || methodNode.name == "" - private val shouldCheckUninitializedObjectCopy = !methodNode.invisibleAnnotations.orEmpty() - .any { it.desc == AVOID_UNINITIALIZED_OBJECT_COPYING_CHECK_ANNOTATION_DESCRIPTOR } - fun run() { - if (!shouldCheckUninitializedObjectCopy) return val interpreter = UninitializedNewValueMarkerInterpreter(methodNode.instructions) val frames = CustomFramesMethodAnalyzer( @@ -183,7 +174,7 @@ class UninitializedStoresProcessor( assert(insn.opcode == Opcodes.INVOKESPECIAL) { "Expected opcode Opcodes.INVOKESPECIAL for , but ${insn.opcode} found" } val paramsCountIncludingReceiver = Type.getArgumentTypes((insn as MethodInsnNode).desc).size + 1 val newValue = peek(paramsCountIncludingReceiver) as? UninitializedNewValue ?: - if (isInSpecialMethod || !shouldCheckUninitializedObjectCopy) + if (isInSpecialMethod) return null else error("Expected value generated with NEW") diff --git a/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/parcel/ParcelableCodegenExtension.kt b/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/parcel/ParcelableCodegenExtension.kt index e976e601c9c..7bec740109b 100644 --- a/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/parcel/ParcelableCodegenExtension.kt +++ b/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/parcel/ParcelableCodegenExtension.kt @@ -18,36 +18,34 @@ package org.jetbrains.kotlin.android.parcel import kotlinx.android.parcel.TypeParceler 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.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.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.FunctionGenerationStrategy.CodegenBased import org.jetbrains.kotlin.codegen.ImplementationBodyCodegen import org.jetbrains.kotlin.codegen.OwnerKind 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.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.incremental.components.NoLookupLocation.WHEN_GET_ALL_DESCRIPTORS import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtElement -import org.jetbrains.kotlin.resolve.BindingContext 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.module -import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin 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.types.KotlinType import org.jetbrains.kotlin.types.TypeUtils @@ -104,8 +102,6 @@ open class ParcelableCodegenExtension : ExpressionCodegenExtension { val containerAsmType = codegen.typeMapper.mapType(this.defaultType) return findFunction(WRITE_TO_PARCEL)?.write(codegen) { - v.visitAnnotation(UninitializedStoresProcessor.AVOID_UNINITIALIZED_OBJECT_COPYING_CHECK_ANNOTATION_DESCRIPTOR, false) - if (parcelerObject != null) { val (companionAsmType, companionFieldName) = getCompanionClassType(containerAsmType, parcelerObject) @@ -117,7 +113,13 @@ open class ParcelableCodegenExtension : ExpressionCodegenExtension { "(${containerAsmType.descriptor}${PARCEL_TYPE.descriptor}I)V", false) } 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) { val asmType = codegen.typeMapper.mapType(type) @@ -188,10 +190,9 @@ open class ParcelableCodegenExtension : ExpressionCodegenExtension { properties: List ) { 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) { - v.visitAnnotation(UninitializedStoresProcessor.AVOID_UNINITIALIZED_OBJECT_COPYING_CHECK_ANNOTATION_DESCRIPTOR, false) - if (parcelerObject != null) { val (companionAsmType, companionFieldName) = getCompanionClassType(containerAsmType, parcelerObject) @@ -204,7 +205,12 @@ open class ParcelableCodegenExtension : ExpressionCodegenExtension { v.dup() 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) { val asmType = codegen.typeMapper.mapType(type) diff --git a/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/parcel/ParcelableDeclarationChecker.kt b/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/parcel/ParcelableDeclarationChecker.kt index 98b6c0f81ba..4c92b56a3ed 100644 --- a/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/parcel/ParcelableDeclarationChecker.kt +++ b/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/parcel/ParcelableDeclarationChecker.kt @@ -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.ErrorsAndroid 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.KotlinTypeMapper import org.jetbrains.kotlin.descriptors.ClassDescriptor @@ -214,7 +215,12 @@ class ParcelableDeclarationChecker : SimpleDeclarationChecker { try { 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) } catch (e: IllegalArgumentException) { diff --git a/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/parcel/serializers/ParcelSerializer.kt b/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/parcel/serializers/ParcelSerializer.kt index 8e84524659d..38ba8701ec0 100644 --- a/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/parcel/serializers/ParcelSerializer.kt +++ b/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/parcel/serializers/ParcelSerializer.kt @@ -18,6 +18,7 @@ package org.jetbrains.kotlin.android.parcel.serializers import kotlinx.android.parcel.WriteWith import org.jetbrains.kotlin.android.parcel.isParcelize +import org.jetbrains.kotlin.codegen.FrameMap import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassKind @@ -54,7 +55,8 @@ interface ParcelSerializer { data class ParcelSerializerContext( val typeMapper: KotlinTypeMapper, val containerClassType: Type, - val typeParcelers: List + val typeParcelers: List, + val frameMap: FrameMap ) { fun findParcelerClass(type: KotlinType): KotlinType? { return typeParcelers.firstOrNull { it.first == type }?.second @@ -152,7 +154,7 @@ interface ParcelSerializer { } 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 @@ -168,7 +170,7 @@ interface ParcelSerializer { keyType.type, typeMapper.mapTypeSafe(keyType.type, forceBoxed = true), context, forceBoxed = true, strict = strict()) val valueSerializer = get( 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)) @@ -206,16 +208,16 @@ interface ParcelSerializer { Method("readSparseBooleanArray")) 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, PrimitiveTypeParcelSerializer.getInstance(Type.LONG_TYPE))) + asmType, PrimitiveTypeParcelSerializer.getInstance(Type.LONG_TYPE), context.frameMap)) asmType.isSparseArray() -> { val elementType = type.arguments.single().type val elementSerializer = get( 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) diff --git a/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/parcel/serializers/ParcelSerializers.kt b/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/parcel/serializers/ParcelSerializers.kt index c8c7c063b57..0e26e0b633e 100644 --- a/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/parcel/serializers/ParcelSerializers.kt +++ b/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/parcel/serializers/ParcelSerializers.kt @@ -19,9 +19,10 @@ package org.jetbrains.kotlin.android.parcel.serializers import kotlinx.android.parcel.Parceler import org.jetbrains.kotlin.android.parcel.serializers.BoxedPrimitiveTypeParcelSerializer.Companion.BOXED_VALUE_METHOD_NAMES import org.jetbrains.kotlin.codegen.AsmUtil +import org.jetbrains.kotlin.codegen.FrameMap import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper +import org.jetbrains.kotlin.codegen.useTmpVar import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.org.objectweb.asm.Label import org.jetbrains.org.objectweb.asm.Type @@ -186,8 +187,9 @@ internal fun InstructionAdapter.castIfNeeded(targetType: Type) { internal class ListSetParcelSerializer( asmType: Type, - elementSerializer: ParcelSerializer -) : AbstractCollectionParcelSerializer(asmType, elementSerializer) { + elementSerializer: ParcelSerializer, + frameMap: FrameMap +) : AbstractCollectionParcelSerializer(asmType, elementSerializer, frameMap) { override fun getSize(v: InstructionAdapter) { v.invokeinterface("java/util/Collection", "size", "()I") } @@ -216,8 +218,9 @@ internal class ListSetParcelSerializer( internal class MapParcelSerializer( asmType: Type, private val keySerializer: ParcelSerializer, - elementSerializer: ParcelSerializer -) : AbstractCollectionParcelSerializer(asmType, elementSerializer) { + elementSerializer: ParcelSerializer, + frameMap: FrameMap +) : AbstractCollectionParcelSerializer(asmType, elementSerializer, frameMap) { override fun getSize(v: InstructionAdapter) { v.invokeinterface("java/util/Map", "size", "()I") } @@ -260,7 +263,8 @@ internal class MapParcelSerializer( abstract internal class AbstractCollectionParcelSerializer( final override val asmType: Type, - protected val elementSerializer: ParcelSerializer + protected val elementSerializer: ParcelSerializer, + private val frameMap: FrameMap ) : ParcelSerializer { protected val collectionType: Type = Type.getObjectType(when (asmType.internalName) { "java/util/List" -> "java/util/ArrayList" @@ -331,27 +335,27 @@ abstract internal class AbstractCollectionParcelSerializer( } 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, "", "(I)V", false) // -> list + } else { + v.invokespecial(collectionType.internalName, "", "()V", false) // -> list + } + + v.load(sizeVarIndex, Type.INT_TYPE) // -> list, size + } + val nextLoopIteration = 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, "", "(I)V", false) // -> size, list - } - else { - v.pop() // -> size, list, list - v.invokespecial(collectionType.internalName, "", "()V", false) // -> size, list - } - v.visitLabel(nextLoopIteration) - v.swap() // -> list, size v.dupX1() // -> size, list, size v.ifeq(loopIsOver) // -> size, list v.dup() // -> size, list, list @@ -362,16 +366,19 @@ abstract internal class AbstractCollectionParcelSerializer( v.aconst(-1) // -> list, size, (-1) v.add(Type.INT_TYPE) // -> list, (size - 1) - v.swap() // -> size, list v.goTo(nextLoopIteration) v.visitLabel(loopIsOver) - v.swap() + v.swap() // -> list, size 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") override fun writeValue(v: InstructionAdapter) { @@ -421,12 +428,17 @@ internal class SparseArrayParcelSerializer(override val asmType: Type, private v } override fun readValue(v: InstructionAdapter) { - v.invokevirtual(PARCEL_TYPE.internalName, "readInt", "()I", false) // -> size - v.dup() // -> size, size - v.anew(asmType) // -> size, size, arr - v.dupX2() // -> arr, size, size, arr - v.swap() // -> arr, size, arr, size - v.invokespecial(asmType.internalName, "", "(I)V", false) // -> arr, size + frameMap.useTmpVar(Type.INT_TYPE) { sizeVarIndex -> + v.invokevirtual(PARCEL_TYPE.internalName, "readInt", "()I", false) // -> size + v.store(sizeVarIndex, Type.INT_TYPE) // -> (empty) + + v.anew(asmType) // -> arr + v.dup() // -> arr, arr + v.load(sizeVarIndex, Type.INT_TYPE) // -> arr, arr, size + v.invokespecial(asmType.internalName, "", "(I)V", false) // -> arr + + v.load(sizeVarIndex, Type.INT_TYPE) // -> arr, size + } val nextLoopIteration = Label() val loopIsOver = Label() diff --git a/plugins/android-extensions/android-extensions-compiler/testData/parcel/codegen/IBinderIInterface.txt b/plugins/android-extensions/android-extensions-compiler/testData/parcel/codegen/IBinderIInterface.txt index 185455e6074..c0a7ffbda44 100644 --- a/plugins/android-extensions/android-extensions-compiler/testData/parcel/codegen/IBinderIInterface.txt +++ b/plugins/android-extensions/android-extensions-compiler/testData/parcel/codegen/IBinderIInterface.txt @@ -18,13 +18,13 @@ public final class User$Creator : java/lang/Object, android/os/Parcelable$Creato CHECKCAST ALOAD (1) INVOKEVIRTUAL (android/os/Parcel, readInt, ()I) - DUP + ISTORE (2) NEW - DUP_X1 - SWAP + DUP + ILOAD (2) INVOKESPECIAL (java/util/ArrayList, , (I)V) + ILOAD (2) LABEL (L2) - SWAP DUP_X1 IFEQ (L3) DUP @@ -35,7 +35,6 @@ public final class User$Creator : java/lang/Object, android/os/Parcelable$Creato SWAP LDC (-1) IADD - SWAP GOTO (L2) LABEL (L3) SWAP diff --git a/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/javac/KaptJavaLog.kt b/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/javac/KaptJavaLog.kt index 0e00bfdedb4..41f1df602da 100644 --- a/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/javac/KaptJavaLog.kt +++ b/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/javac/KaptJavaLog.kt @@ -75,8 +75,6 @@ class KaptJavaLog( } override fun report(diagnostic: JCDiagnostic) { - System.err.println("Diagnostic code: ${diagnostic.code}") - if (diagnostic.type == JCDiagnostic.DiagnosticType.ERROR && diagnostic.code in IGNORED_DIAGNOSTICS) { return }