diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java index b14f04b251a..b8ac8c66642 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java @@ -66,8 +66,7 @@ import static org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.SYN import static org.jetbrains.kotlin.resolve.BindingContext.VARIABLE; import static org.jetbrains.kotlin.resolve.DescriptorUtils.isCompanionObject; import static org.jetbrains.kotlin.resolve.DescriptorUtils.isTopLevelDeclaration; -import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE; -import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.PROPERTY_METADATA_TYPE; +import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.*; import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.NO_ORIGIN; import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt.Synthetic; import static org.jetbrains.org.objectweb.asm.Opcodes.*; @@ -509,18 +508,41 @@ public abstract class MemberCodegen", + Type.getMethodDescriptor(Type.VOID_TYPE, K_DECLARATION_CONTAINER_TYPE, JAVA_STRING_TYPE, JAVA_STRING_TYPE), false + ); + value = StackValue.onStack(implType); + Method wrapper = PropertyReferenceCodegen.getWrapperMethodForPropertyReference(property, receiverCount); + iv.invokestatic(REFLECTION, wrapper.getName(), wrapper.getDescriptor(), false); + } + else { + ReceiverParameterDescriptor dispatchReceiver = property.getDispatchReceiverParameter(); - //noinspection ConstantConditions - StackValue value = createOrGetClInitCodegen().generatePropertyReference( - delegatedProperties.get(i).getDelegate(), property, property, - dispatchReceiver != null ? new TransientReceiver(dispatchReceiver.getType()) : ReceiverValue.NO_RECEIVER - ); + //noinspection ConstantConditions + value = createOrGetClInitCodegen().generatePropertyReference( + delegatedProperties.get(i).getDelegate(), property, property, + dispatchReceiver != null ? new TransientReceiver(dispatchReceiver.getType()) : ReceiverValue.NO_RECEIVER + ); + } value.put(PROPERTY_METADATA_TYPE, iv); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyReferenceCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyReferenceCodegen.kt index 56038f0855e..290a9626e33 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyReferenceCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyReferenceCodegen.kt @@ -35,10 +35,7 @@ import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue import org.jetbrains.kotlin.resolve.scopes.receivers.ScriptReceiver import org.jetbrains.kotlin.utils.sure -import org.jetbrains.org.objectweb.asm.Opcodes.ACC_FINAL -import org.jetbrains.org.objectweb.asm.Opcodes.ACC_PUBLIC -import org.jetbrains.org.objectweb.asm.Opcodes.ACC_SUPER -import org.jetbrains.org.objectweb.asm.Opcodes.V1_6 +import org.jetbrains.org.objectweb.asm.Opcodes.* import org.jetbrains.org.objectweb.asm.Type import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter import org.jetbrains.org.objectweb.asm.commons.Method @@ -74,24 +71,7 @@ public class PropertyReferenceCodegen( 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 { - wrapperMethod = when (receiverCount) { - 2 -> when { - target.isVar -> method("mutableProperty2", K_MUTABLE_PROPERTY2_TYPE, MUTABLE_PROPERTY_REFERENCE2) - else -> method("property2", K_PROPERTY2_TYPE, PROPERTY_REFERENCE2) - } - 1 -> 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) - } - } - } + private val wrapperMethod = getWrapperMethodForPropertyReference(target, receiverCount) override fun generateDeclaration() { v.defineClass( @@ -127,16 +107,7 @@ public class PropertyReferenceCodegen( } generateMethod("property reference getSignature", ACC_PUBLIC, method("getSignature", JAVA_STRING_TYPE)) { - target as PropertyDescriptor - - val getter = target.getGetter() ?: run { - val defaultGetter = DescriptorFactory.createDefaultGetter(target, Annotations.EMPTY) - defaultGetter.initialize(target.getType()) - defaultGetter - } - - val method = typeMapper.mapSignature(getter).getAsmMethod() - aconst(method.getName() + method.getDescriptor()) + aconst(getPropertyReferenceSignature(target as PropertyDescriptor, state)) } generateAccessors() @@ -207,4 +178,35 @@ public class PropertyReferenceCodegen( StackValue.operation(wrapperMethod.getReturnType()) { iv -> iv.getstatic(asmType.getInternalName(), JvmAbi.INSTANCE_FIELD, wrapperMethod.getReturnType().getDescriptor()) } + + companion object { + @JvmStatic + fun getPropertyReferenceSignature(property: PropertyDescriptor, state: GenerationState): String { + val getter = + property.getter ?: DescriptorFactory.createDefaultGetter(property, Annotations.EMPTY).apply { + initialize(property.type) + } + + val method = state.typeMapper.mapSignature(getter).asmMethod + return method.name + method.descriptor + } + + @JvmStatic + fun getWrapperMethodForPropertyReference(property: VariableDescriptor, receiverCount: Int): Method { + return when (receiverCount) { + 2 -> when { + property.isVar -> method("mutableProperty2", K_MUTABLE_PROPERTY2_TYPE, MUTABLE_PROPERTY_REFERENCE2) + else -> method("property2", K_PROPERTY2_TYPE, PROPERTY_REFERENCE2) + } + 1 -> when { + property.isVar -> method("mutableProperty1", K_MUTABLE_PROPERTY1_TYPE, MUTABLE_PROPERTY_REFERENCE1) + else -> method("property1", K_PROPERTY1_TYPE, PROPERTY_REFERENCE1) + } + else -> when { + property.isVar -> method("mutableProperty0", K_MUTABLE_PROPERTY0_TYPE, MUTABLE_PROPERTY_REFERENCE0) + else -> method("property0", K_PROPERTY0_TYPE, PROPERTY_REFERENCE0) + } + } + } + } } diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/AsmTypes.java b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/AsmTypes.java index 70657d72a4d..f2e46e210fa 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/AsmTypes.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/AsmTypes.java @@ -42,6 +42,17 @@ public class AsmTypes { public static final Type MUTABLE_PROPERTY_REFERENCE1 = Type.getObjectType("kotlin/jvm/internal/MutablePropertyReference1"); public static final Type MUTABLE_PROPERTY_REFERENCE2 = Type.getObjectType("kotlin/jvm/internal/MutablePropertyReference2"); + public static final Type[] PROPERTY_REFERENCE_IMPL = { + Type.getObjectType("kotlin/jvm/internal/PropertyReference0Impl"), + Type.getObjectType("kotlin/jvm/internal/PropertyReference1Impl"), + Type.getObjectType("kotlin/jvm/internal/PropertyReference2Impl") + }; + public static final Type[] MUTABLE_PROPERTY_REFERENCE_IMPL = { + Type.getObjectType("kotlin/jvm/internal/MutablePropertyReference0Impl"), + Type.getObjectType("kotlin/jvm/internal/MutablePropertyReference1Impl"), + Type.getObjectType("kotlin/jvm/internal/MutablePropertyReference2Impl") + }; + public static final Type K_CLASS_TYPE = reflect("KClass"); public static final Type K_CLASS_ARRAY_TYPE = Type.getObjectType("[" + K_CLASS_TYPE.getDescriptor()); public static final Type K_DECLARATION_CONTAINER_TYPE = reflect("KDeclarationContainer"); diff --git a/core/runtime.jvm/src/kotlin/jvm/internal/FunctionReferenceImpl.java b/core/runtime.jvm/src/kotlin/jvm/internal/FunctionReferenceImpl.java new file mode 100644 index 00000000000..2f02c4f979e --- /dev/null +++ b/core/runtime.jvm/src/kotlin/jvm/internal/FunctionReferenceImpl.java @@ -0,0 +1,47 @@ +/* + * 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 kotlin.jvm.internal; + +import kotlin.reflect.KDeclarationContainer; + +public class FunctionReferenceImpl extends FunctionReference { + private final KDeclarationContainer owner; + private final String name; + private final String signature; + + public FunctionReferenceImpl(int arity, KDeclarationContainer owner, String name, String signature) { + super(arity); + this.owner = owner; + this.name = name; + this.signature = signature; + } + + @Override + public KDeclarationContainer getOwner() { + return owner; + } + + @Override + public String getName() { + return name; + } + + @Override + public String getSignature() { + return signature; + } +} diff --git a/core/runtime.jvm/src/kotlin/jvm/internal/MutablePropertyReference0Impl.java b/core/runtime.jvm/src/kotlin/jvm/internal/MutablePropertyReference0Impl.java new file mode 100644 index 00000000000..88f4f9caa43 --- /dev/null +++ b/core/runtime.jvm/src/kotlin/jvm/internal/MutablePropertyReference0Impl.java @@ -0,0 +1,56 @@ + /* + * 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 kotlin.jvm.internal; + +import kotlin.reflect.KDeclarationContainer; + +public class MutablePropertyReference0Impl extends MutablePropertyReference0 { + private final KDeclarationContainer owner; + private final String name; + private final String signature; + + public MutablePropertyReference0Impl(KDeclarationContainer owner, String name, String signature) { + this.owner = owner; + this.name = name; + this.signature = signature; + } + + @Override + public KDeclarationContainer getOwner() { + return owner; + } + + @Override + public String getName() { + return name; + } + + @Override + public String getSignature() { + return signature; + } + + @Override + public Object get() { + return getGetter().call(); + } + + @Override + public void set(Object value) { + getSetter().call(value); + } +} diff --git a/core/runtime.jvm/src/kotlin/jvm/internal/MutablePropertyReference1Impl.java b/core/runtime.jvm/src/kotlin/jvm/internal/MutablePropertyReference1Impl.java new file mode 100644 index 00000000000..0f283bdad9b --- /dev/null +++ b/core/runtime.jvm/src/kotlin/jvm/internal/MutablePropertyReference1Impl.java @@ -0,0 +1,56 @@ +/* + * 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 kotlin.jvm.internal; + +import kotlin.reflect.KDeclarationContainer; + +public class MutablePropertyReference1Impl extends MutablePropertyReference1 { + private final KDeclarationContainer owner; + private final String name; + private final String signature; + + public MutablePropertyReference1Impl(KDeclarationContainer owner, String name, String signature) { + this.owner = owner; + this.name = name; + this.signature = signature; + } + + @Override + public KDeclarationContainer getOwner() { + return owner; + } + + @Override + public String getName() { + return name; + } + + @Override + public String getSignature() { + return signature; + } + + @Override + public Object get(Object receiver) { + return getGetter().call(receiver); + } + + @Override + public void set(Object receiver, Object value) { + getSetter().call(receiver, value); + } +} diff --git a/core/runtime.jvm/src/kotlin/jvm/internal/MutablePropertyReference2Impl.java b/core/runtime.jvm/src/kotlin/jvm/internal/MutablePropertyReference2Impl.java new file mode 100644 index 00000000000..178aa4b3d64 --- /dev/null +++ b/core/runtime.jvm/src/kotlin/jvm/internal/MutablePropertyReference2Impl.java @@ -0,0 +1,56 @@ +/* + * 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 kotlin.jvm.internal; + +import kotlin.reflect.KDeclarationContainer; + +public class MutablePropertyReference2Impl extends MutablePropertyReference2 { + private final KDeclarationContainer owner; + private final String name; + private final String signature; + + public MutablePropertyReference2Impl(KDeclarationContainer owner, String name, String signature) { + this.owner = owner; + this.name = name; + this.signature = signature; + } + + @Override + public KDeclarationContainer getOwner() { + return owner; + } + + @Override + public String getName() { + return name; + } + + @Override + public String getSignature() { + return signature; + } + + @Override + public Object get(Object receiver1, Object receiver2) { + return getGetter().call(receiver1, receiver2); + } + + @Override + public void set(Object receiver1, Object receiver2, Object value) { + getSetter().call(receiver1, receiver2, value); + } +} diff --git a/core/runtime.jvm/src/kotlin/jvm/internal/PropertyReference0Impl.java b/core/runtime.jvm/src/kotlin/jvm/internal/PropertyReference0Impl.java new file mode 100644 index 00000000000..7f731aecb91 --- /dev/null +++ b/core/runtime.jvm/src/kotlin/jvm/internal/PropertyReference0Impl.java @@ -0,0 +1,51 @@ +/* + * 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 kotlin.jvm.internal; + +import kotlin.reflect.KDeclarationContainer; + +public class PropertyReference0Impl extends PropertyReference0 { + private final KDeclarationContainer owner; + private final String name; + private final String signature; + + public PropertyReference0Impl(KDeclarationContainer owner, String name, String signature) { + this.owner = owner; + this.name = name; + this.signature = signature; + } + + @Override + public KDeclarationContainer getOwner() { + return owner; + } + + @Override + public String getName() { + return name; + } + + @Override + public String getSignature() { + return signature; + } + + @Override + public Object get() { + return getGetter().call(); + } +} diff --git a/core/runtime.jvm/src/kotlin/jvm/internal/PropertyReference1Impl.java b/core/runtime.jvm/src/kotlin/jvm/internal/PropertyReference1Impl.java new file mode 100644 index 00000000000..6eaf3803e2f --- /dev/null +++ b/core/runtime.jvm/src/kotlin/jvm/internal/PropertyReference1Impl.java @@ -0,0 +1,51 @@ +/* + * 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 kotlin.jvm.internal; + +import kotlin.reflect.KDeclarationContainer; + +public class PropertyReference1Impl extends PropertyReference1 { + private final KDeclarationContainer owner; + private final String name; + private final String signature; + + public PropertyReference1Impl(KDeclarationContainer owner, String name, String signature) { + this.owner = owner; + this.name = name; + this.signature = signature; + } + + @Override + public KDeclarationContainer getOwner() { + return owner; + } + + @Override + public String getName() { + return name; + } + + @Override + public String getSignature() { + return signature; + } + + @Override + public Object get(Object receiver) { + return getGetter().call(receiver); + } +} diff --git a/core/runtime.jvm/src/kotlin/jvm/internal/PropertyReference2Impl.java b/core/runtime.jvm/src/kotlin/jvm/internal/PropertyReference2Impl.java new file mode 100644 index 00000000000..8d7a62628eb --- /dev/null +++ b/core/runtime.jvm/src/kotlin/jvm/internal/PropertyReference2Impl.java @@ -0,0 +1,51 @@ +/* + * 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 kotlin.jvm.internal; + +import kotlin.reflect.KDeclarationContainer; + +public class PropertyReference2Impl extends PropertyReference2 { + private final KDeclarationContainer owner; + private final String name; + private final String signature; + + public PropertyReference2Impl(KDeclarationContainer owner, String name, String signature) { + this.owner = owner; + this.name = name; + this.signature = signature; + } + + @Override + public KDeclarationContainer getOwner() { + return owner; + } + + @Override + public String getName() { + return name; + } + + @Override + public String getSignature() { + return signature; + } + + @Override + public Object get(Object receiver1, Object receiver2) { + return getGetter().call(receiver1, receiver2); + } +}