Support boxing/unboxing for method return types

This commit is contained in:
Mikhail Zarechenskiy
2018-02-05 11:43:10 +03:00
parent 390c214943
commit c5c8d84719
15 changed files with 210 additions and 100 deletions
@@ -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) {
@@ -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?
@@ -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
@@ -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)
}
@@ -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
@@ -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")
@@ -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)