Fix bridge methods generation when inline class types are used
This commit is contained in:
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.codegen.coroutines.SuspendFunctionGenerationStrategy
|
||||
import org.jetbrains.kotlin.codegen.coroutines.SuspendInlineFunctionGenerationStrategy;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
||||
import org.jetbrains.kotlin.codegen.state.TypeMapperUtilsKt;
|
||||
import org.jetbrains.kotlin.config.JvmDefaultMode;
|
||||
import org.jetbrains.kotlin.config.JvmTarget;
|
||||
import org.jetbrains.kotlin.config.LanguageFeature;
|
||||
@@ -615,7 +616,7 @@ public class FunctionCodegen {
|
||||
KotlinTypeMapper typeMapper = parentCodegen.typeMapper;
|
||||
if (BuiltinSpecialBridgesUtil.shouldHaveTypeSafeBarrier(functionDescriptor, typeMapper::mapAsmMethod)) {
|
||||
generateTypeCheckBarrierIfNeeded(
|
||||
new InstructionAdapter(mv), functionDescriptor, signature.getReturnType(), /* delegateParameterTypes = */null);
|
||||
new InstructionAdapter(mv), functionDescriptor, signature.getReturnType(), null, typeMapper);
|
||||
}
|
||||
|
||||
Label methodEnd;
|
||||
@@ -1422,16 +1423,23 @@ public class FunctionCodegen {
|
||||
Type[] argTypes = bridge.getArgumentTypes();
|
||||
Type[] originalArgTypes = delegateTo.getArgumentTypes();
|
||||
|
||||
List<ParameterDescriptor> allKotlinParameters = new ArrayList<>(argTypes.length);
|
||||
if (descriptor.getExtensionReceiverParameter() != null) allKotlinParameters.add(descriptor.getExtensionReceiverParameter());
|
||||
allKotlinParameters.addAll(descriptor.getValueParameters());
|
||||
|
||||
boolean safeToUseKotlinTypes = allKotlinParameters.size() == argTypes.length;
|
||||
|
||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
MemberCodegen.markLineNumberForDescriptor(owner.getThisDescriptor(), iv);
|
||||
|
||||
if (delegateTo.getArgumentTypes().length > 0 && isSpecialBridge) {
|
||||
generateTypeCheckBarrierIfNeeded(iv, descriptor, bridge.getReturnType(), delegateTo.getArgumentTypes());
|
||||
generateTypeCheckBarrierIfNeeded(iv, descriptor, bridge.getReturnType(), delegateTo.getArgumentTypes(), typeMapper);
|
||||
}
|
||||
|
||||
iv.load(0, OBJECT_TYPE);
|
||||
for (int i = 0, reg = 1; i < argTypes.length; i++) {
|
||||
StackValue.local(reg, argTypes[i]).put(originalArgTypes[i], iv);
|
||||
KotlinType kotlinType = safeToUseKotlinTypes ? allKotlinParameters.get(i).getType() : null;
|
||||
StackValue.local(reg, argTypes[i], kotlinType).put(originalArgTypes[i], kotlinType, iv);
|
||||
//noinspection AssignmentToForLoopParameter
|
||||
reg += argTypes[i].getSize();
|
||||
}
|
||||
@@ -1451,7 +1459,8 @@ public class FunctionCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
StackValue.coerce(delegateTo.getReturnType(), bridge.getReturnType(), iv);
|
||||
KotlinType returnType = descriptor.getReturnType();
|
||||
StackValue.coerce(delegateTo.getReturnType(), returnType, bridge.getReturnType(), returnType, iv);
|
||||
iv.areturn(bridge.getReturnType());
|
||||
|
||||
endVisit(mv, "bridge method", origin);
|
||||
@@ -1461,7 +1470,8 @@ public class FunctionCodegen {
|
||||
@NotNull InstructionAdapter iv,
|
||||
@NotNull FunctionDescriptor descriptor,
|
||||
@NotNull Type returnType,
|
||||
@Nullable Type[] delegateParameterTypes
|
||||
@Nullable Type[] delegateParameterTypes,
|
||||
@NotNull KotlinTypeMapper typeMapper
|
||||
) {
|
||||
BuiltinMethodsWithSpecialGenericSignature.TypeSafeBarrierDescription typeSafeBarrierDescription =
|
||||
BuiltinMethodsWithSpecialGenericSignature.getDefaultValueForOverriddenBuiltinFunction(descriptor);
|
||||
@@ -1489,7 +1499,13 @@ public class FunctionCodegen {
|
||||
iv.ifnull(defaultBranch);
|
||||
}
|
||||
else {
|
||||
CodegenUtilKt.generateIsCheck(iv, kotlinType, boxType(delegateParameterTypes[i]));
|
||||
Type targetBoxedType;
|
||||
if (InlineClassesUtilsKt.isInlineClassType(kotlinType)) {
|
||||
targetBoxedType = typeMapper.mapTypeAsDeclaration(kotlinType);
|
||||
} else {
|
||||
targetBoxedType = boxType(delegateParameterTypes[i]);
|
||||
}
|
||||
CodegenUtilKt.generateIsCheck(iv, kotlinType, targetBoxedType);
|
||||
iv.ifeq(defaultBranch);
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+34
@@ -0,0 +1,34 @@
|
||||
// !LANGUAGE: +InlineClasses
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
|
||||
inline class InlinedComparable(val x: Int) : Comparable<InlinedComparable> {
|
||||
override fun compareTo(other: InlinedComparable): Int {
|
||||
return x.compareTo(other.x)
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> generic(c: Comparable<T>, element: T) = c.compareTo(element)
|
||||
|
||||
interface Base<T> {
|
||||
fun Base<T>.foo(a: Base<T>, b: T): Base<T>
|
||||
}
|
||||
|
||||
inline class InlinedBase(val x: Int) : Base<InlinedBase> {
|
||||
override fun Base<InlinedBase>.foo(a: Base<InlinedBase>, b: InlinedBase): Base<InlinedBase> {
|
||||
return if (a is InlinedBase) InlinedBase(a.x + b.x) else this
|
||||
}
|
||||
|
||||
fun double(): InlinedBase {
|
||||
return this.foo(this, this) as InlinedBase
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val a = InlinedComparable(42)
|
||||
if (generic(a, a) != 0) return "Fail 1"
|
||||
|
||||
val b = InlinedBase(3)
|
||||
if (b.double().x != 6) return "Fail 2"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+6
@@ -13,6 +13,10 @@ inline class MyUIntArray(private val storage: IntArray) : Collection<MyUInt> {
|
||||
override fun isEmpty(): Boolean = TODO()
|
||||
}
|
||||
|
||||
fun <T> checkBoxed(c: Collection<T>, element: T): Boolean {
|
||||
return c.contains(element) && c.containsAll(listOf(element))
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val uints = MyUIntArray(intArrayOf(0, 1, 42))
|
||||
|
||||
@@ -21,5 +25,7 @@ fun box(): String {
|
||||
val ints = listOf(MyUInt(1), MyUInt(0))
|
||||
if (!uints.containsAll(ints)) return "Fail 2"
|
||||
|
||||
if (!checkBoxed(uints, MyUInt(0))) return "Fail 3"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+3
-4
@@ -8,7 +8,7 @@ inline class UIntArray(private val intArray: IntArray) {
|
||||
|
||||
inline class UIntIterator(private val intIterator: IntIterator) : Iterator<UInt> {
|
||||
override fun next(): UInt {
|
||||
return UInt(intIterator.next())
|
||||
return UInt(intIterator.next()) // box inside bridge that returns java/lang/Object
|
||||
}
|
||||
|
||||
override fun hasNext(): Boolean {
|
||||
@@ -27,7 +27,7 @@ fun test() {
|
||||
|
||||
fun takeUInt(u: UInt) {}
|
||||
|
||||
// 0 INVOKESTATIC UInt\$Erased.box
|
||||
// 1 INVOKESTATIC UInt\$Erased.box
|
||||
// 0 INVOKEVIRTUAL UInt.unbox
|
||||
|
||||
// 0 INVOKEVIRTUAL UIntIterator.iterator
|
||||
@@ -35,5 +35,4 @@ fun takeUInt(u: UInt) {}
|
||||
|
||||
// 0 intValue
|
||||
|
||||
// inside wrong bridge
|
||||
// 1 valueOf
|
||||
// 0 valueOf
|
||||
Generated
+5
@@ -11169,6 +11169,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/boxUnboxOfInlineClassForCapturedVars.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("bridgesWhenInlineClassImplementsGenericInterface.kt")
|
||||
public void testBridgesWhenInlineClassImplementsGenericInterface() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/bridgesWhenInlineClassImplementsGenericInterface.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("callComputablePropertyInsideInlineClass.kt")
|
||||
public void testCallComputablePropertyInsideInlineClass() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/callComputablePropertyInsideInlineClass.kt");
|
||||
|
||||
+5
@@ -11169,6 +11169,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/boxUnboxOfInlineClassForCapturedVars.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("bridgesWhenInlineClassImplementsGenericInterface.kt")
|
||||
public void testBridgesWhenInlineClassImplementsGenericInterface() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/bridgesWhenInlineClassImplementsGenericInterface.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("callComputablePropertyInsideInlineClass.kt")
|
||||
public void testCallComputablePropertyInsideInlineClass() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/callComputablePropertyInsideInlineClass.kt");
|
||||
|
||||
+5
@@ -11169,6 +11169,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/boxUnboxOfInlineClassForCapturedVars.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("bridgesWhenInlineClassImplementsGenericInterface.kt")
|
||||
public void testBridgesWhenInlineClassImplementsGenericInterface() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/bridgesWhenInlineClassImplementsGenericInterface.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("callComputablePropertyInsideInlineClass.kt")
|
||||
public void testCallComputablePropertyInsideInlineClass() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/callComputablePropertyInsideInlineClass.kt");
|
||||
|
||||
@@ -38,4 +38,4 @@ fun KotlinType.isNullableUnderlyingType(): Boolean {
|
||||
val underlyingType = unsubstitutedUnderlyingType() ?: return false
|
||||
|
||||
return TypeUtils.isNullableType(underlyingType)
|
||||
}
|
||||
}
|
||||
|
||||
+5
@@ -10834,6 +10834,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/boxUnboxOfInlineClassForCapturedVars.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("bridgesWhenInlineClassImplementsGenericInterface.kt")
|
||||
public void testBridgesWhenInlineClassImplementsGenericInterface() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/bridgesWhenInlineClassImplementsGenericInterface.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("callComputablePropertyInsideInlineClass.kt")
|
||||
public void testCallComputablePropertyInsideInlineClass() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/callComputablePropertyInsideInlineClass.kt");
|
||||
|
||||
+5
@@ -9712,6 +9712,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/boxUnboxOfInlineClassForCapturedVars.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("bridgesWhenInlineClassImplementsGenericInterface.kt")
|
||||
public void testBridgesWhenInlineClassImplementsGenericInterface() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/bridgesWhenInlineClassImplementsGenericInterface.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("callComputablePropertyInsideInlineClass.kt")
|
||||
public void testCallComputablePropertyInsideInlineClass() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/callComputablePropertyInsideInlineClass.kt");
|
||||
|
||||
Reference in New Issue
Block a user