From 670565b251a8f5ddee673a6f7bb3c88c78710bf6 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Fri, 10 Jul 2015 17:11:49 +0300 Subject: [PATCH] Wrap property reference instance before storing to static field --- .../kotlin/codegen/ClosureCodegen.java | 3 +- .../kotlin/codegen/MemberCodegen.java | 18 +++++-- .../codegen/PropertyReferenceCodegen.kt | 53 ++++++++++--------- .../org/jetbrains/kotlin/utils/functions.kt | 13 +++-- 4 files changed, 51 insertions(+), 36 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ClosureCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ClosureCodegen.java index e8c1415888d..f5375b206fd 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ClosureCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ClosureCodegen.java @@ -37,6 +37,7 @@ import org.jetbrains.kotlin.resolve.BindingContext; import org.jetbrains.kotlin.resolve.DescriptorUtils; import org.jetbrains.kotlin.types.JetType; import org.jetbrains.kotlin.types.expressions.OperatorConventions; +import org.jetbrains.kotlin.utils.UtilsPackage; import org.jetbrains.org.objectweb.asm.MethodVisitor; import org.jetbrains.org.objectweb.asm.Type; import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter; @@ -202,7 +203,7 @@ public class ClosureCodegen extends MemberCodegen { this.constructor = generateConstructor(); if (isConst(closure)) { - generateConstInstance(asmType); + generateConstInstance(asmType, asmType, UtilsPackage.doNothing()); } genClosureFields(closure, v, typeMapper); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java index 97724959a7b..c4a779ffd2d 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java @@ -17,7 +17,9 @@ package org.jetbrains.kotlin.codegen; import com.intellij.openapi.progress.ProcessCanceledException; +import kotlin.Unit; import kotlin.jvm.functions.Function0; +import kotlin.jvm.functions.Function1; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.codegen.context.*; @@ -533,15 +535,21 @@ public abstract class MemberCodegen initialization + ) { + v.newField(OtherOrigin(element), ACC_STATIC | ACC_FINAL | ACC_PUBLIC, JvmAbi.INSTANCE_FIELD, fieldAsmType.getDescriptor(), + null, null); if (state.getClassBuilderMode() == ClassBuilderMode.FULL) { InstructionAdapter iv = createOrGetClInitCodegen().v; - iv.anew(asmType); + iv.anew(thisAsmType); iv.dup(); - iv.invokespecial(asmType.getInternalName(), "", "()V", false); - iv.putstatic(asmType.getInternalName(), JvmAbi.INSTANCE_FIELD, asmType.getDescriptor()); + iv.invokespecial(thisAsmType.getInternalName(), "", "()V", false); + initialization.invoke(iv); + iv.putstatic(thisAsmType.getInternalName(), JvmAbi.INSTANCE_FIELD, fieldAsmType.getDescriptor()); } } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyReferenceCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyReferenceCodegen.kt index be819795dc8..16f054df8d2 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyReferenceCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyReferenceCodegen.kt @@ -54,11 +54,27 @@ public class PropertyReferenceCodegen( ) : MemberCodegen(state, parentCodegen, context, expression, classBuilder) { private val target = resolvedCall.getResultingDescriptor() private val asmType = typeMapper.mapClass(classDescriptor) - private val superAsmType: Type + + // e.g. MutablePropertyReference0 + private val superAsmType = typeMapper.mapClass(classDescriptor.getSuperClassNotAny().sure { "No super class for $classDescriptor" }) + + // e.g. mutableProperty0(Lkotlin/jvm/internal/MutablePropertyReference0;)Lkotlin/reflect/KMutableProperty0; + private val wrapperMethod: Method init { - val superClass = classDescriptor.getSuperClassNotAny().sure { "No super class for $classDescriptor" } - superAsmType = typeMapper.mapClass(superClass) + val hasReceiver = target.getDispatchReceiverParameter() != null || target.getExtensionReceiverParameter() != null + val isMutable = target.isVar() + + wrapperMethod = when { + hasReceiver -> when { + isMutable -> method("mutableProperty1", K_MUTABLE_PROPERTY1_TYPE, MUTABLE_PROPERTY_REFERENCE1) + else -> method("property1", K_PROPERTY1_TYPE, PROPERTY_REFERENCE1) + } + else -> when { + isMutable -> method("mutableProperty0", K_MUTABLE_PROPERTY0_TYPE, MUTABLE_PROPERTY_REFERENCE0) + else -> method("property0", K_PROPERTY0_TYPE, PROPERTY_REFERENCE0) + } + } } override fun generateDeclaration() { @@ -77,8 +93,9 @@ public class PropertyReferenceCodegen( // TODO: ImplementationBodyCodegen.markLineNumberForSyntheticFunction? override fun generateBody() { - // TODO: instance should be already wrapped by Reflection - generateConstInstance(asmType) + generateConstInstance(asmType, wrapperMethod.getReturnType()) { iv -> + iv.invokestatic(REFLECTION, wrapperMethod.getName(), wrapperMethod.getDescriptor(), false) + } generateMethod("property reference init", 0, method("", Type.VOID_TYPE)) { load(0, OBJECT_TYPE) @@ -102,7 +119,7 @@ public class PropertyReferenceCodegen( defaultGetter } - val method = typeMapper.mapSignature(getter.sure { "No getter: $target" }).getAsmMethod() + val method = typeMapper.mapSignature(getter).getAsmMethod() aconst(method.getName() + method.getDescriptor()) } @@ -178,24 +195,8 @@ public class PropertyReferenceCodegen( writeKotlinSyntheticClassAnnotation(v, KotlinSyntheticClass.Kind.CALLABLE_REFERENCE_WRAPPER) } - public fun putInstanceOnStack(): StackValue { - val hasReceiver = target.getDispatchReceiverParameter() != null || target.getExtensionReceiverParameter() != null - - val method = - when { - hasReceiver -> when { - target.isVar() -> method("mutableProperty1", K_MUTABLE_PROPERTY1_TYPE, MUTABLE_PROPERTY_REFERENCE1) - else -> method("property1", K_PROPERTY1_TYPE, PROPERTY_REFERENCE1) - } - else -> when { - target.isVar() -> method("mutableProperty0", K_MUTABLE_PROPERTY0_TYPE, MUTABLE_PROPERTY_REFERENCE0) - else -> method("property0", K_PROPERTY0_TYPE, PROPERTY_REFERENCE0) - } - } - - return StackValue.operation(method.getReturnType()) { iv -> - iv.getstatic(asmType.getInternalName(), JvmAbi.INSTANCE_FIELD, asmType.getDescriptor()) - iv.invokestatic(REFLECTION, method.getName(), method.getDescriptor(), false) - } - } + public fun putInstanceOnStack(): StackValue = + StackValue.operation(wrapperMethod.getReturnType()) { iv -> + iv.getstatic(asmType.getInternalName(), JvmAbi.INSTANCE_FIELD, wrapperMethod.getReturnType().getDescriptor()) + } } diff --git a/core/util.runtime/src/org/jetbrains/kotlin/utils/functions.kt b/core/util.runtime/src/org/jetbrains/kotlin/utils/functions.kt index 1b538942cd6..5414a37327f 100644 --- a/core/util.runtime/src/org/jetbrains/kotlin/utils/functions.kt +++ b/core/util.runtime/src/org/jetbrains/kotlin/utils/functions.kt @@ -16,12 +16,17 @@ package org.jetbrains.kotlin.utils -private val IDENTITY: Function1 = { it } +private val IDENTITY: (Any?) -> Any? = { it } suppress("UNCHECKED_CAST") -public fun identity(): Function1 = IDENTITY as Function1 +public fun identity(): (T) -> T = IDENTITY as (T) -> T -private val ALWAYS_TRUE: Function1 = { true } +private val ALWAYS_TRUE: (Any?) -> Boolean = { true } -public fun alwaysTrue(): Function1 = ALWAYS_TRUE +public fun alwaysTrue(): (T) -> Boolean = ALWAYS_TRUE + + +public val DO_NOTHING: (Any?) -> Unit = { } + +public fun doNothing(): (T) -> Unit = DO_NOTHING