Add intrinsic for KCallable.name property Fixes #KT-11531
This commit is contained in:
committed by
Alexander Udalov
parent
b8e2533b58
commit
4a619db721
@@ -38,13 +38,10 @@ import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
|
||||
import org.jetbrains.kotlin.codegen.context.*;
|
||||
import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension;
|
||||
import org.jetbrains.kotlin.codegen.inline.*;
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicCallable;
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethod;
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods;
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicPropertyGetter;
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.*;
|
||||
import org.jetbrains.kotlin.codegen.pseudoInsns.PseudoInsnsKt;
|
||||
import org.jetbrains.kotlin.codegen.signature.JvmSignatureWriter;
|
||||
import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter;
|
||||
import org.jetbrains.kotlin.codegen.signature.JvmSignatureWriter;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
||||
import org.jetbrains.kotlin.codegen.when.SwitchCodegen;
|
||||
@@ -1983,8 +1980,14 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
VariableAsFunctionResolvedCall call = (VariableAsFunctionResolvedCall) resolvedCall;
|
||||
resolvedCall = call.getVariableCall();
|
||||
}
|
||||
receiver = StackValue.receiver(resolvedCall, receiver, this, null);
|
||||
|
||||
descriptor = resolvedCall.getResultingDescriptor();
|
||||
|
||||
//Check early if KCallableNameProperty is applicable to prevent closure generation
|
||||
StackValue intrinsicResult = applyIntrinsic(descriptor, KCallableNameProperty.class, resolvedCall, receiver);
|
||||
if (intrinsicResult != null) return intrinsicResult;
|
||||
|
||||
receiver = StackValue.receiver(resolvedCall, receiver, this, null);
|
||||
if (descriptor instanceof FakeCallableDescriptorForObject) {
|
||||
descriptor = ((FakeCallableDescriptorForObject) descriptor).getReferencedDescriptor();
|
||||
}
|
||||
@@ -1997,17 +2000,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
if (isSyntheticField) {
|
||||
descriptor = ((SyntheticFieldDescriptor) descriptor).getPropertyDescriptor();
|
||||
}
|
||||
if (descriptor instanceof CallableMemberDescriptor) {
|
||||
CallableMemberDescriptor memberDescriptor = DescriptorUtils.unwrapFakeOverride((CallableMemberDescriptor) descriptor);
|
||||
|
||||
IntrinsicMethod intrinsic = state.getIntrinsics().getIntrinsic(memberDescriptor);
|
||||
if (intrinsic instanceof IntrinsicPropertyGetter) {
|
||||
//TODO: intrinsic properties (see intermediateValueForProperty)
|
||||
Type returnType = typeMapper.mapType(memberDescriptor);
|
||||
StackValue intrinsicResult = ((IntrinsicPropertyGetter) intrinsic).generate(resolvedCall, this, returnType, receiver);
|
||||
if (intrinsicResult != null) return intrinsicResult;
|
||||
}
|
||||
}
|
||||
StackValue intrinsicResult = applyIntrinsic(descriptor, IntrinsicPropertyGetter.class, resolvedCall, receiver);
|
||||
if (intrinsicResult != null) return intrinsicResult;
|
||||
|
||||
if (descriptor instanceof PropertyDescriptor) {
|
||||
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
|
||||
@@ -2056,6 +2051,25 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
throw new UnsupportedOperationException("don't know how to generate reference " + descriptor);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private StackValue applyIntrinsic(
|
||||
DeclarationDescriptor descriptor,
|
||||
Class<? extends IntrinsicPropertyGetter> intrinsicType,
|
||||
ResolvedCall<?> resolvedCall,
|
||||
@NotNull StackValue receiver
|
||||
) {
|
||||
if (descriptor instanceof CallableMemberDescriptor) {
|
||||
CallableMemberDescriptor memberDescriptor = DescriptorUtils.unwrapFakeOverride((CallableMemberDescriptor) descriptor);
|
||||
IntrinsicMethod intrinsic = state.getIntrinsics().getIntrinsic(memberDescriptor);
|
||||
if (intrinsicType.isInstance(intrinsic)) {
|
||||
//TODO: intrinsic properties (see intermediateValueForProperty)
|
||||
Type returnType = typeMapper.mapType(memberDescriptor);
|
||||
return ((IntrinsicPropertyGetter) intrinsic).generate(resolvedCall, this, returnType, receiver);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private ClassDescriptor getSuperCallTarget(@NotNull Call call) {
|
||||
KtSuperExpression superExpression = CallResolverUtilKt.getSuperCallExpression(call);
|
||||
|
||||
@@ -62,6 +62,7 @@ public class IntrinsicMethods {
|
||||
public IntrinsicMethods() {
|
||||
intrinsicsMap.registerIntrinsic(KOTLIN_JVM, RECEIVER_PARAMETER_FQ_NAME, "javaClass", -1, new JavaClassProperty());
|
||||
intrinsicsMap.registerIntrinsic(KOTLIN_JVM, KotlinBuiltIns.FQ_NAMES.kClass, "java", -1, new KClassJavaProperty());
|
||||
intrinsicsMap.registerIntrinsic(KotlinBuiltIns.FQ_NAMES.kCallable.toSafe(), null, "name", -1, new KCallableNameProperty());
|
||||
intrinsicsMap.registerIntrinsic(new FqName("kotlin.jvm.internal.unsafe"), null, "monitorEnter", 1, MonitorInstruction.MONITOR_ENTER);
|
||||
intrinsicsMap.registerIntrinsic(new FqName("kotlin.jvm.internal.unsafe"), null, "monitorExit", 1, MonitorInstruction.MONITOR_EXIT);
|
||||
intrinsicsMap.registerIntrinsic(KOTLIN_JVM, KotlinBuiltIns.FQ_NAMES.array, "isArrayOf", 0, new IsArrayOf());
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2010-2016 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 org.jetbrains.kotlin.codegen.intrinsics
|
||||
|
||||
import org.jetbrains.kotlin.codegen.ExpressionCodegen
|
||||
import org.jetbrains.kotlin.codegen.StackValue
|
||||
import org.jetbrains.kotlin.psi.KtCallableReferenceExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
|
||||
class KCallableNameProperty : IntrinsicPropertyGetter() {
|
||||
override fun generate(resolvedCall: ResolvedCall<*>?, codegen: ExpressionCodegen, returnType: Type, receiver: StackValue): StackValue? {
|
||||
val expressionReceiver = resolvedCall!!.dispatchReceiver as? ExpressionReceiver ?: return null
|
||||
val expression = expressionReceiver.expression as? KtCallableReferenceExpression ?: return null
|
||||
val callableReference = expression.callableReference
|
||||
val descriptor = callableReference.getResolvedCall(codegen.bindingContext)?.resultingDescriptor ?: return null
|
||||
val name = descriptor.name.asString()
|
||||
|
||||
return StackValue.operation(returnType) { iv ->
|
||||
iv.aconst(name)
|
||||
StackValue.coerce(AsmTypes.JAVA_STRING_TYPE, returnType, iv)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
class A {
|
||||
val a = ""
|
||||
fun b() = ""
|
||||
|
||||
fun test() {
|
||||
val a = A::a.name
|
||||
val b = A::b.name
|
||||
val c = ::A.name
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
@kotlin.Metadata
|
||||
public final class A {
|
||||
private final @org.jetbrains.annotations.NotNull field a: java.lang.String
|
||||
public method <init>(): void
|
||||
public final @org.jetbrains.annotations.NotNull method b(): java.lang.String
|
||||
public final @org.jetbrains.annotations.NotNull method getA(): java.lang.String
|
||||
public final method test(): void
|
||||
}
|
||||
@@ -35,6 +35,12 @@ public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/bytecodeListing"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("callableNameIntrinsic.kt")
|
||||
public void testCallableNameIntrinsic() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeListing/callableNameIntrinsic.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("defaultImpls.kt")
|
||||
public void testDefaultImpls() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeListing/defaultImpls.kt");
|
||||
|
||||
Reference in New Issue
Block a user