Support boxing/unboxing for method return types
This commit is contained in:
@@ -110,7 +110,7 @@ public class CallReceiver extends StackValue {
|
||||
return new AsmTypeAndKotlinType(typeMapper.mapType(classDescriptor), classDescriptor.getDefaultType());
|
||||
}
|
||||
//noinspection ConstantConditions
|
||||
return new AsmTypeAndKotlinType(callableMethod.getDispatchReceiverType(), null);
|
||||
return new AsmTypeAndKotlinType(callableMethod.getDispatchReceiverType(), callableMethod.getDispatchReceiverKotlinType());
|
||||
}
|
||||
|
||||
// Extract the receiver from the resolved call, workarounding the fact that ResolvedCall#dispatchReceiver doesn't have
|
||||
@@ -147,7 +147,7 @@ public class CallReceiver extends StackValue {
|
||||
}
|
||||
|
||||
return callableMethod != null ?
|
||||
new AsmTypeAndKotlinType(callableMethod.getExtensionReceiverType(), null) :
|
||||
new AsmTypeAndKotlinType(callableMethod.getExtensionReceiverType(), callableMethod.getExtensionReceiverKotlinType()) :
|
||||
new AsmTypeAndKotlinType(typeMapper.mapType(extensionReceiver.getType()), extensionReceiver.getType());
|
||||
}
|
||||
|
||||
|
||||
@@ -1,22 +1,12 @@
|
||||
/*
|
||||
* 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.
|
||||
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen
|
||||
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
|
||||
@@ -25,8 +15,12 @@ interface Callable {
|
||||
|
||||
val dispatchReceiverType: Type?
|
||||
|
||||
val dispatchReceiverKotlinType: KotlinType?
|
||||
|
||||
val extensionReceiverType: Type?
|
||||
|
||||
val extensionReceiverKotlinType: KotlinType?
|
||||
|
||||
val generateCalleeType: Type?
|
||||
|
||||
val valueParameterTypes: List<Type>
|
||||
@@ -35,12 +29,14 @@ interface Callable {
|
||||
|
||||
val returnType: Type
|
||||
|
||||
val returnKotlinType: KotlinType?
|
||||
|
||||
fun genInvokeInstruction(v: InstructionAdapter)
|
||||
|
||||
fun isStaticCall(): Boolean
|
||||
|
||||
fun invokeMethodWithArguments(resolvedCall: ResolvedCall<*>, receiver: StackValue, codegen: ExpressionCodegen): StackValue {
|
||||
return StackValue.functionCall(returnType) {
|
||||
return StackValue.functionCall(returnType, resolvedCall.resultingDescriptor.returnType) {
|
||||
codegen.invokeMethodWithArguments(this, resolvedCall, receiver)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* 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.
|
||||
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen
|
||||
@@ -20,6 +9,7 @@ import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes.INVOKESPECIAL
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes.INVOKESTATIC
|
||||
@@ -35,8 +25,11 @@ class CallableMethod(
|
||||
private val signature: JvmMethodSignature,
|
||||
private val invokeOpcode: Int,
|
||||
override val dispatchReceiverType: Type?,
|
||||
override val dispatchReceiverKotlinType: KotlinType?,
|
||||
override val extensionReceiverType: Type?,
|
||||
override val extensionReceiverKotlinType: KotlinType?,
|
||||
override val generateCalleeType: Type?,
|
||||
override val returnKotlinType: KotlinType?,
|
||||
private val isInterfaceMethod: Boolean = Opcodes.INVOKEINTERFACE == invokeOpcode
|
||||
) : Callable {
|
||||
fun getValueParameters(): List<JvmMethodParameterSignature> =
|
||||
|
||||
@@ -3879,7 +3879,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
|
||||
@NotNull
|
||||
public StackValue generateConstructorCall(@NotNull ResolvedCall<?> resolvedCall, @NotNull Type objectType) {
|
||||
return StackValue.functionCall(objectType, v -> {
|
||||
return StackValue.functionCall(objectType, null, v -> {
|
||||
v.anew(objectType);
|
||||
v.dup();
|
||||
|
||||
|
||||
@@ -717,11 +717,15 @@ public abstract class StackValue {
|
||||
}
|
||||
|
||||
public static StackValue operation(Type type, Function1<InstructionAdapter, Unit> lambda) {
|
||||
return new OperationStackValue(type, lambda);
|
||||
return operation(type, null, lambda);
|
||||
}
|
||||
|
||||
public static StackValue functionCall(Type type, Function1<InstructionAdapter, Unit> lambda) {
|
||||
return new FunctionCallStackValue(type, lambda);
|
||||
public static StackValue operation(Type type, KotlinType kotlinType, Function1<InstructionAdapter, Unit> lambda) {
|
||||
return new OperationStackValue(type, kotlinType, lambda);
|
||||
}
|
||||
|
||||
public static StackValue functionCall(Type type, KotlinType kotlinType, Function1<InstructionAdapter, Unit> lambda) {
|
||||
return new FunctionCallStackValue(type, kotlinType, lambda);
|
||||
}
|
||||
|
||||
public static boolean couldSkipReceiverOnStaticCall(StackValue value) {
|
||||
|
||||
@@ -60,7 +60,11 @@ class StackValueWithLeaveTask(
|
||||
}
|
||||
}
|
||||
|
||||
open class OperationStackValue(resultType: Type, val lambda: (v: InstructionAdapter) -> Unit) : StackValue(resultType) {
|
||||
open class OperationStackValue(
|
||||
resultType: Type,
|
||||
resultKotlinType: KotlinType?,
|
||||
val lambda: (v: InstructionAdapter) -> Unit
|
||||
) : StackValue(resultType, resultKotlinType) {
|
||||
|
||||
override fun putSelector(type: Type, kotlinType: KotlinType?, v: InstructionAdapter) {
|
||||
lambda(v)
|
||||
@@ -68,7 +72,11 @@ open class OperationStackValue(resultType: Type, val lambda: (v: InstructionAdap
|
||||
}
|
||||
}
|
||||
|
||||
class FunctionCallStackValue(resultType: Type, lambda: (v: InstructionAdapter) -> Unit) : OperationStackValue(resultType, lambda)
|
||||
class FunctionCallStackValue(
|
||||
resultType: Type,
|
||||
resultKotlinType: KotlinType?,
|
||||
lambda: (v: InstructionAdapter) -> Unit
|
||||
) : OperationStackValue(resultType, resultKotlinType, lambda)
|
||||
|
||||
fun ValueParameterDescriptor.findJavaDefaultArgumentValue(targetType: Type, typeMapper: KotlinTypeMapper): StackValue {
|
||||
val descriptorWithDefaultValue = DFS.dfs(
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* 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.
|
||||
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen.intrinsics
|
||||
@@ -19,6 +8,7 @@ package org.jetbrains.kotlin.codegen.intrinsics
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil
|
||||
import org.jetbrains.kotlin.codegen.Callable
|
||||
import org.jetbrains.kotlin.codegen.CallableMethod
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
|
||||
@@ -52,6 +42,15 @@ open class IntrinsicCallable(
|
||||
override val parameterTypes: Array<Type>
|
||||
get() = throw UnsupportedOperationException()
|
||||
|
||||
override val dispatchReceiverKotlinType: KotlinType?
|
||||
get() = null
|
||||
|
||||
override val extensionReceiverKotlinType: KotlinType?
|
||||
get() = null
|
||||
|
||||
override val returnKotlinType: KotlinType?
|
||||
get() = null
|
||||
|
||||
override fun isStaticCall() = false
|
||||
|
||||
override val generateCalleeType: Type?
|
||||
|
||||
@@ -745,10 +745,11 @@ public class KotlinTypeMapper {
|
||||
if (descriptor instanceof ConstructorDescriptor) {
|
||||
JvmMethodSignature method = mapSignatureSkipGeneric(descriptor.getOriginal());
|
||||
Type owner = mapOwner(descriptor);
|
||||
String defaultImplDesc = mapDefaultMethod(descriptor.getOriginal(), OwnerKind.IMPLEMENTATION).getDescriptor();
|
||||
FunctionDescriptor originalDescriptor = descriptor.getOriginal();
|
||||
String defaultImplDesc = mapDefaultMethod(originalDescriptor, OwnerKind.IMPLEMENTATION).getDescriptor();
|
||||
return new CallableMethod(
|
||||
owner, owner, defaultImplDesc, method, INVOKESPECIAL,
|
||||
null, null, null, false
|
||||
null, null, null, null, null, originalDescriptor.getReturnType(), false
|
||||
);
|
||||
}
|
||||
|
||||
@@ -764,11 +765,13 @@ public class KotlinTypeMapper {
|
||||
FunctionDescriptor functionDescriptor = findSuperDeclaration(descriptor.getOriginal(), superCall);
|
||||
|
||||
JvmMethodSignature signature;
|
||||
KotlinType returnKotlinType;
|
||||
Type owner;
|
||||
Type ownerForDefaultImpl;
|
||||
FunctionDescriptor baseMethodDescriptor;
|
||||
int invokeOpcode;
|
||||
Type thisClass;
|
||||
KotlinType dispatchReceiverKotlinType;
|
||||
boolean isInterfaceMember = false;
|
||||
|
||||
if (functionParent instanceof ClassDescriptor) {
|
||||
@@ -790,15 +793,19 @@ public class KotlinTypeMapper {
|
||||
|
||||
if (isInterface && (superCall || descriptor.getVisibility() == Visibilities.PRIVATE || isAccessor(descriptor))) {
|
||||
thisClass = mapClass(currentOwner);
|
||||
dispatchReceiverKotlinType = currentOwner.getDefaultType();
|
||||
if (declarationOwner instanceof JavaClassDescriptor || isJvm8InterfaceWithDefaults(declarationOwner)) {
|
||||
invokeOpcode = INVOKESPECIAL;
|
||||
signature = mapSignatureSkipGeneric(functionDescriptor);
|
||||
returnKotlinType = functionDescriptor.getReturnType();
|
||||
owner = thisClass;
|
||||
isInterfaceMember = true;
|
||||
}
|
||||
else {
|
||||
invokeOpcode = INVOKESTATIC;
|
||||
signature = mapSignatureSkipGeneric(descriptor.getOriginal(), OwnerKind.DEFAULT_IMPLS);
|
||||
FunctionDescriptor originalDescriptor = descriptor.getOriginal();
|
||||
signature = mapSignatureSkipGeneric(originalDescriptor, OwnerKind.DEFAULT_IMPLS);
|
||||
returnKotlinType = originalDescriptor.getReturnType();
|
||||
owner = mapDefaultImpls(currentOwner);
|
||||
}
|
||||
}
|
||||
@@ -834,41 +841,53 @@ public class KotlinTypeMapper {
|
||||
signature = isInsideInlineClass
|
||||
? mapSignatureForInlineErasedClassSkipGeneric(functionToCall)
|
||||
: mapSignatureSkipGeneric(functionToCall);
|
||||
returnKotlinType = functionToCall.getReturnType();
|
||||
|
||||
ClassDescriptor receiver = (currentIsInterface && !originalIsInterface) || currentOwner instanceof FunctionClassDescriptor
|
||||
? declarationOwner
|
||||
: currentOwner;
|
||||
owner = isInsideInlineClass ? mapErasedInlineClass(receiver) : mapClass(receiver);
|
||||
thisClass = owner;
|
||||
dispatchReceiverKotlinType = receiver.getDefaultType();
|
||||
}
|
||||
}
|
||||
else {
|
||||
signature = mapSignatureSkipGeneric(functionDescriptor.getOriginal());
|
||||
FunctionDescriptor originalDescriptor = functionDescriptor.getOriginal();
|
||||
signature = mapSignatureSkipGeneric(originalDescriptor);
|
||||
returnKotlinType = originalDescriptor.getReturnType();
|
||||
owner = mapOwner(functionDescriptor);
|
||||
ownerForDefaultImpl = owner;
|
||||
baseMethodDescriptor = functionDescriptor;
|
||||
if (functionParent instanceof PackageFragmentDescriptor) {
|
||||
invokeOpcode = INVOKESTATIC;
|
||||
thisClass = null;
|
||||
dispatchReceiverKotlinType = null;
|
||||
}
|
||||
else if (functionDescriptor instanceof ConstructorDescriptor) {
|
||||
invokeOpcode = INVOKESPECIAL;
|
||||
thisClass = null;
|
||||
dispatchReceiverKotlinType = null;
|
||||
}
|
||||
else {
|
||||
invokeOpcode = INVOKEVIRTUAL;
|
||||
thisClass = owner;
|
||||
DeclarationDescriptor ownerDescriptor = functionDescriptor.getContainingDeclaration();
|
||||
dispatchReceiverKotlinType = ownerDescriptor instanceof ClassDescriptor ?
|
||||
((ClassDescriptor) ownerDescriptor).getDefaultType() : null;
|
||||
}
|
||||
}
|
||||
|
||||
Type calleeType = isLocalFunction(functionDescriptor) ? owner : null;
|
||||
|
||||
Type receiverParameterType;
|
||||
KotlinType extensionReceiverKotlinType;
|
||||
ReceiverParameterDescriptor receiverParameter = functionDescriptor.getOriginal().getExtensionReceiverParameter();
|
||||
if (receiverParameter != null) {
|
||||
receiverParameterType = mapType(receiverParameter.getType());
|
||||
extensionReceiverKotlinType = receiverParameter.getType();
|
||||
receiverParameterType = mapType(extensionReceiverKotlinType);
|
||||
}
|
||||
else {
|
||||
extensionReceiverKotlinType = null;
|
||||
receiverParameterType = null;
|
||||
}
|
||||
|
||||
@@ -876,8 +895,9 @@ public class KotlinTypeMapper {
|
||||
|
||||
return new CallableMethod(
|
||||
owner, ownerForDefaultImpl, defaultImplDesc, signature, invokeOpcode,
|
||||
thisClass, receiverParameterType, calleeType,
|
||||
isJvm8Target ? isInterfaceMember : invokeOpcode == INVOKEINTERFACE );
|
||||
thisClass, dispatchReceiverKotlinType, receiverParameterType, extensionReceiverKotlinType, calleeType, returnKotlinType,
|
||||
isJvm8Target ? isInterfaceMember : invokeOpcode == INVOKEINTERFACE
|
||||
);
|
||||
}
|
||||
|
||||
private boolean isJvm8InterfaceWithDefaults(@NotNull ClassDescriptor ownerForDefault) {
|
||||
|
||||
Reference in New Issue
Block a user