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) {
|
||||
|
||||
+12
-13
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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.backend.jvm.intrinsics
|
||||
@@ -19,6 +8,7 @@ package org.jetbrains.kotlin.backend.jvm.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
|
||||
import java.lang.UnsupportedOperationException
|
||||
@@ -53,6 +43,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?
|
||||
|
||||
+8
-13
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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.backend.jvm.intrinsics
|
||||
@@ -63,8 +52,12 @@ open class IrIntrinsicFunction(
|
||||
get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates.
|
||||
override val dispatchReceiverType: Type?
|
||||
get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates.
|
||||
override val dispatchReceiverKotlinType: KotlinType?
|
||||
get() = null
|
||||
override val extensionReceiverType: Type?
|
||||
get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates.
|
||||
override val extensionReceiverKotlinType: KotlinType?
|
||||
get() = null
|
||||
override val generateCalleeType: Type?
|
||||
get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates.
|
||||
override val valueParameterTypes: List<Type>
|
||||
@@ -73,6 +66,8 @@ open class IrIntrinsicFunction(
|
||||
get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates.
|
||||
override val returnType: Type
|
||||
get() = signature.returnType
|
||||
override val returnKotlinType: KotlinType?
|
||||
get() = null
|
||||
|
||||
override fun isStaticCall(): Boolean {
|
||||
return false
|
||||
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
// !LANGUAGE: +InlineClasses
|
||||
|
||||
inline class Foo(val a: Int) {
|
||||
fun member(): String = ""
|
||||
|
||||
fun asResult() = a
|
||||
}
|
||||
|
||||
fun <T> id(x: T): T = x
|
||||
fun <T> T.idExtension(): T = this
|
||||
|
||||
fun Foo.extension() {}
|
||||
|
||||
|
||||
fun test(f: Foo): String {
|
||||
id(f) // box
|
||||
id(f).idExtension() // box
|
||||
|
||||
id(f).member() // box unbox
|
||||
id(f).extension() // box unbox
|
||||
|
||||
val a = id(f) // box unbox
|
||||
val b = id(f).idExtension() // box unbox
|
||||
|
||||
if (a.asResult() != 10) return "fail"
|
||||
if (b.asResult() != 10) return "fail"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val f = Foo(10)
|
||||
|
||||
return test(f)
|
||||
}
|
||||
Vendored
+28
@@ -0,0 +1,28 @@
|
||||
// !LANGUAGE: +InlineClasses
|
||||
|
||||
inline class Foo(val a: Int) {
|
||||
fun member(): String = ""
|
||||
}
|
||||
|
||||
fun <T> id(x: T): T = x
|
||||
fun <T> T.idExtension(): T = this
|
||||
|
||||
fun Foo.extension() {}
|
||||
|
||||
|
||||
fun test(f: Foo) {
|
||||
id(f) // box
|
||||
id(f).idExtension() // box
|
||||
|
||||
id(f).member() // box unbox
|
||||
id(f).extension() // box unbox
|
||||
|
||||
val a = id(f) // box unbox
|
||||
val b = id(f).idExtension() // box unbox
|
||||
}
|
||||
|
||||
// 6 INVOKESTATIC Foo\$Erased.box
|
||||
// 4 INVOKEVIRTUAL Foo.unbox
|
||||
|
||||
// 0 valueOf
|
||||
// 0 intValue
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
// !LANGUAGE: +InlineClasses
|
||||
|
||||
inline class Foo(val x: Int) {
|
||||
fun member() {}
|
||||
}
|
||||
|
||||
fun Foo?.extensionOnNullable() {}
|
||||
|
||||
fun test(f: Foo?) {
|
||||
if (f != null) {
|
||||
f.member() // unbox
|
||||
}
|
||||
|
||||
if (f != null) {
|
||||
f.extensionOnNullable()
|
||||
}
|
||||
|
||||
if (f != null) {
|
||||
val a = f
|
||||
a.member() // unbox
|
||||
}
|
||||
}
|
||||
|
||||
// 0 INVOKESTATIC Foo\$Erased.box
|
||||
// 2 INVOKEVIRTUAL Foo.unbox
|
||||
|
||||
// 0 valueOf
|
||||
// 0 intValue
|
||||
@@ -1914,6 +1914,12 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/bytecodeText/inlineClasses"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("boxUnboxInlineClassFromMethodReturnType.kt")
|
||||
public void testBoxUnboxInlineClassFromMethodReturnType() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/inlineClasses/boxUnboxInlineClassFromMethodReturnType.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("callMemberMethodsInsideInlineClass.kt")
|
||||
public void testCallMemberMethodsInsideInlineClass() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/inlineClasses/callMemberMethodsInsideInlineClass.kt");
|
||||
@@ -1937,6 +1943,18 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/inlineClasses/inlineClassBoxingOnFunctionCall.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("unboxInlineClassAfterSafeCall.kt")
|
||||
public void testUnboxInlineClassAfterSafeCall() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/inlineClasses/unboxInlineClassAfterSafeCall.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("unboxInlineClassesAfterSmartCasts.kt")
|
||||
public void testUnboxInlineClassesAfterSmartCasts() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/inlineClasses/unboxInlineClassesAfterSmartCasts.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/bytecodeText/interfaces")
|
||||
|
||||
+6
-19
@@ -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.android.synthetic.codegen
|
||||
@@ -20,8 +9,8 @@ import kotlinx.android.extensions.CacheImplementation
|
||||
import kotlinx.android.extensions.CacheImplementation.NO_CACHE
|
||||
import org.jetbrains.kotlin.android.synthetic.AndroidConst
|
||||
import org.jetbrains.kotlin.android.synthetic.codegen.AndroidContainerType.LAYOUT_CONTAINER
|
||||
import org.jetbrains.kotlin.android.synthetic.descriptors.ContainerOptionsProxy
|
||||
import org.jetbrains.kotlin.android.synthetic.descriptors.AndroidSyntheticPackageFragmentDescriptor
|
||||
import org.jetbrains.kotlin.android.synthetic.descriptors.ContainerOptionsProxy
|
||||
import org.jetbrains.kotlin.android.synthetic.res.AndroidSyntheticFunction
|
||||
import org.jetbrains.kotlin.android.synthetic.res.AndroidSyntheticProperty
|
||||
import org.jetbrains.kotlin.codegen.*
|
||||
@@ -37,9 +26,7 @@ import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
||||
import org.jetbrains.org.objectweb.asm.Label
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes.ACC_PRIVATE
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes.ACC_PUBLIC
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes.ACC_SYNTHETIC
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes.*
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
|
||||
@@ -96,13 +83,13 @@ abstract class AbstractAndroidExtensionsExpressionCodegenExtension : ExpressionC
|
||||
val containerOptions = ContainerOptionsProxy.create(container)
|
||||
|
||||
if (!containerOptions.getCacheOrDefault(resolvedCall.call.calleeExpression).hasCache) {
|
||||
return StackValue.functionCall(Type.VOID_TYPE) {}
|
||||
return StackValue.functionCall(Type.VOID_TYPE, null) {}
|
||||
}
|
||||
|
||||
if (containerOptions.containerType == AndroidContainerType.UNKNOWN) return null
|
||||
val actualReceiver = StackValue.receiver(resolvedCall, receiver, c.codegen, null)
|
||||
|
||||
return StackValue.functionCall(Type.VOID_TYPE) {
|
||||
return StackValue.functionCall(Type.VOID_TYPE, null) {
|
||||
val bytecodeClassName = c.typeMapper.mapType(container).internalName
|
||||
|
||||
actualReceiver.put(c.typeMapper.mapType(container), it)
|
||||
|
||||
Reference in New Issue
Block a user