Rename receiver$0 in CallableReference to receiver

#KT-15449 Fixed
This commit is contained in:
Mikhael Bogdanov
2016-12-28 14:21:00 +01:00
parent 4774d19890
commit 2566a7a25e
17 changed files with 96 additions and 29 deletions
@@ -95,6 +95,7 @@ public class AsmUtil {
.put(JavaVisibilities.PACKAGE_VISIBILITY, NO_FLAG_PACKAGE_PRIVATE)
.build();
public static final String BOUND_REFERENCE_RECEIVER = "receiver";
public static final String RECEIVER_NAME = "$receiver";
public static final String CAPTURED_RECEIVER_FIELD = "receiver$0";
public static final String CAPTURED_THIS_FIELD = "this$0";
@@ -91,7 +91,6 @@ import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor;
import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.kotlin.types.TypeProjection;
import org.jetbrains.kotlin.types.TypeUtils;
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
import org.jetbrains.kotlin.types.expressions.DoubleColonLHS;
import org.jetbrains.kotlin.types.typesApproximation.CapturedTypeApproximationKt;
import org.jetbrains.kotlin.util.OperatorNameConventions;
@@ -3269,7 +3268,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
FunctionDescriptor functionDescriptor = bindingContext.get(FUNCTION, expression);
if (functionDescriptor != null) {
FunctionReferenceGenerationStrategy strategy =
new FunctionReferenceGenerationStrategy(state, functionDescriptor, resolvedCall, receiverAsmType, null);
new FunctionReferenceGenerationStrategy(state, functionDescriptor, resolvedCall, receiverAsmType, null, false);
return genClosure(
expression, functionDescriptor, strategy, null,
@@ -42,13 +42,15 @@ public class FunctionReferenceGenerationStrategy extends FunctionGenerationStrat
private final FunctionDescriptor functionDescriptor;
private final Type receiverType; // non-null for bound references
private final StackValue receiverValue;
private final boolean isInliningStrategy;
public FunctionReferenceGenerationStrategy(
@NotNull GenerationState state,
@NotNull FunctionDescriptor functionDescriptor,
@NotNull ResolvedCall<?> resolvedCall,
@Nullable Type receiverType,
@Nullable StackValue receiverValue
@Nullable StackValue receiverValue,
boolean isInliningStrategy
) {
super(state);
this.resolvedCall = resolvedCall;
@@ -56,6 +58,7 @@ public class FunctionReferenceGenerationStrategy extends FunctionGenerationStrat
this.functionDescriptor = functionDescriptor;
this.receiverType = receiverType;
this.receiverValue = receiverValue;
this.isInliningStrategy = isInliningStrategy;
assert receiverType != null || receiverValue == null
: "A receiver value is provided for unbound function reference. Either this is a bound reference and you forgot " +
"to pass receiverType, or you accidentally passed some receiverValue for a reference without receiver";
@@ -187,7 +190,7 @@ public class FunctionReferenceGenerationStrategy extends FunctionGenerationStrat
if (receiverType != null) {
ClassDescriptor classDescriptor = (ClassDescriptor) codegen.getContext().getParentContext().getContextDescriptor();
Type asmType = codegen.getState().getTypeMapper().mapClass(classDescriptor);
return CallableReferenceUtilKt.capturedBoundReferenceReceiver(asmType, receiverType);
return CallableReferenceUtilKt.capturedBoundReferenceReceiver(asmType, receiverType, isInliningStrategy);
}
// 0 is this (the callable reference class), 1 is the invoke() method's first parameter
@@ -146,12 +146,12 @@ class PropertyReferenceCodegen(
private fun generateAccessors() {
val getFunction = findGetFunction(localVariableDescriptorForReference)
val getImpl = createFakeOpenDescriptor(getFunction, classDescriptor)
functionCodegen.generateMethod(JvmDeclarationOrigin.NO_ORIGIN, getImpl, PropertyReferenceGenerationStrategy(true, getFunction, target, asmType, receiverType, element, state))
functionCodegen.generateMethod(JvmDeclarationOrigin.NO_ORIGIN, getImpl, PropertyReferenceGenerationStrategy(true, getFunction, target, asmType, receiverType, element, state, false))
if (!ReflectionTypes.isNumberedKMutablePropertyType(localVariableDescriptorForReference.type)) return
val setFunction = localVariableDescriptorForReference.type.memberScope.getContributedFunctions(OperatorNameConventions.SET, NoLookupLocation.FROM_BACKEND).single()
val setImpl = createFakeOpenDescriptor(setFunction, classDescriptor)
functionCodegen.generateMethod(JvmDeclarationOrigin.NO_ORIGIN, setImpl, PropertyReferenceGenerationStrategy(false, setFunction, target, asmType, receiverType, element, state))
functionCodegen.generateMethod(JvmDeclarationOrigin.NO_ORIGIN, setImpl, PropertyReferenceGenerationStrategy(false, setFunction, target, asmType, receiverType, element, state, false))
}
@@ -243,7 +243,8 @@ class PropertyReferenceCodegen(
val asmType: Type,
val receiverType: Type?,
val expression: KtElement,
state: GenerationState
state: GenerationState,
val isInliningStrategy: Boolean
) :
FunctionGenerationStrategy.CodegenBased(state) {
override fun doGenerateBody(codegen: ExpressionCodegen, signature: JvmMethodSignature) {
@@ -258,7 +259,7 @@ class PropertyReferenceCodegen(
val expectedReceiver = target.dispatchReceiverParameter ?: target.extensionReceiverParameter ?:
throw AssertionError("receiverType: $receiverType; no dispatch or extension receiver: $target")
val expectedReceiverType = typeMapper.mapType(expectedReceiver.type)
capturedBoundReferenceReceiver(asmType, expectedReceiverType).put(expectedReceiverType, v)
capturedBoundReferenceReceiver(asmType, expectedReceiverType, isInliningStrategy).put(expectedReceiverType, v)
}
else {
val receivers = originalFunctionDesc.valueParameters.dropLast(if (isGetter) 0 else 1)
@@ -24,10 +24,15 @@ import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
fun capturedBoundReferenceReceiver(ownerType: Type, expectedReceiverType: Type): StackValue =
fun capturedBoundReferenceReceiver(ownerType: Type, expectedReceiverType: Type, isInliningStrategy: Boolean): StackValue =
StackValue.operation(expectedReceiverType) { iv ->
iv.load(0, ownerType)
iv.getfield(ownerType.internalName, AsmUtil.CAPTURED_RECEIVER_FIELD, AsmTypes.OBJECT_TYPE.descriptor)
iv.getfield(
ownerType.internalName,
//HACK for inliner - it should recognize field as captured receiver
if (isInliningStrategy) AsmUtil.CAPTURED_RECEIVER_FIELD else AsmUtil.BOUND_REFERENCE_RECEIVER,
AsmTypes.OBJECT_TYPE.descriptor
)
StackValue.coerce(AsmTypes.OBJECT_TYPE, expectedReceiverType, iv)
}
@@ -581,8 +581,7 @@ public class InlineCodegen extends CallGenerator {
Type asmType = state.getTypeMapper().mapClass(lambdaInfo.getClassDescriptor());
PropertyReferenceInfo info = lambdaInfo.getPropertyReferenceInfo();
strategy = new PropertyReferenceCodegen.PropertyReferenceGenerationStrategy(
true, info.getGetFunction(), info.getTarget(), asmType, receiverType, lambdaInfo.expression, state
);
true, info.getGetFunction(), info.getTarget(), asmType, receiverType, lambdaInfo.expression, state, true);
}
else {
strategy = new FunctionReferenceGenerationStrategy(
@@ -591,7 +590,8 @@ public class InlineCodegen extends CallGenerator {
CallUtilKt
.getResolvedCallWithAssert(callableReferenceExpression.getCallableReference(), codegen.getBindingContext()),
receiverType,
null
null,
true
);
}
}