Skip call to the underlying value of inline class

This commit is contained in:
Mikhail Zarechenskiy
2018-02-08 12:18:52 +03:00
parent 2c279978c8
commit c86d3e354b
10 changed files with 134 additions and 6 deletions
@@ -1672,14 +1672,13 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
if (descriptor instanceof PropertyDescriptor) {
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
// `this` is represented as first parameter of function in erased inline class
boolean isThisOfErasedInlineClass =
contextKind() == OwnerKind.ERASED_INLINE_CLASS &&
boolean isUnderlyingPropertyOfInlineClass =
InlineClassesUtilsKt.isInlineClass(propertyDescriptor.getContainingDeclaration()) &&
JvmCodegenUtil.hasBackingField(propertyDescriptor, contextKind(), bindingContext);
if (isThisOfErasedInlineClass) {
Type underlyingRepresentationType = typeMapper.mapType(propertyDescriptor.getType());
return StackValue.local(0, underlyingRepresentationType);
if (isUnderlyingPropertyOfInlineClass) {
KotlinType propertyType = propertyDescriptor.getType();
return StackValue.underlyingValueOfInlineClass(typeMapper.mapType(propertyType), propertyType, receiver);
}
Collection<ExpressionCodegenExtension> codegenExtensions = ExpressionCodegenExtension.Companion.getInstances(state.getProject());
@@ -291,6 +291,14 @@ public abstract class StackValue {
return new CollectionElement(collectionElementReceiver, type, kotlinType, getter, setter, codegen);
}
public static UnderlyingValueOfInlineClass underlyingValueOfInlineClass(
@NotNull Type type,
@Nullable KotlinType kotlinType,
@NotNull StackValue receiver
) {
return new UnderlyingValueOfInlineClass(type, kotlinType, receiver);
}
@NotNull
public static Field field(@NotNull Type type, @NotNull Type owner, @NotNull String name, boolean isStatic, @NotNull StackValue receiver) {
return field(type, null, owner, name, isStatic, receiver, null);
@@ -1004,6 +1012,24 @@ public abstract class StackValue {
}
}
public static class UnderlyingValueOfInlineClass extends StackValueWithSimpleReceiver {
public UnderlyingValueOfInlineClass(
@NotNull Type type,
@Nullable KotlinType kotlinType,
@NotNull StackValue receiver
) {
super(type, kotlinType, false, false, receiver, true);
}
@Override
public void putSelector(
@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v
) {
coerceTo(type, kotlinType, v);
}
}
public static class CollectionElementReceiver extends StackValue {
private final Callable callable;
private final boolean isGetter;
@@ -0,0 +1,16 @@
// !LANGUAGE: +InlineClasses
inline class UInt(val value: Int) {
operator fun plus(other: UInt) = UInt(value + other.value)
fun otherValue(other: UInt) = other.value
}
fun box(): String {
val a = UInt(10)
val b = UInt(20)
if (a.otherValue(b) != 20) return "fail 1"
if ((a + b).value != 30) return "fail 2"
return "OK"
}
@@ -0,0 +1,16 @@
// !LANGUAGE: +InlineClasses
inline class UInt(val value: Int)
fun box(): String {
val a = UInt(123)
if(a.value != 123) return "fail"
val c = a.value.hashCode()
if (c.hashCode() != 123.hashCode()) return "fail"
val b = UInt(100).value + a.value
if (b != 223) return "faile"
return "OK"
}
@@ -0,0 +1,17 @@
// !LANGUAGE: +InlineClasses
inline class UInt(val value: Int)
fun test(u1: UInt, u2: UInt) {
val a = u1.value
val b = u1.value.hashCode() // box int to call hashCode
val c = u1.value + u2.value
}
// 0 INVOKESTATIC UInt\$Erased.getValue
// 0 INVOKESTATIC UInt\$Erased.box
// 0 INVOKEVIRTUAL UInt.unbox
// 1 valueOf
// 0 intValue
@@ -10467,6 +10467,18 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
doTest(fileName);
}
@TestMetadata("referToUnderlyingPropertyInsideInlineClass.kt")
public void testReferToUnderlyingPropertyInsideInlineClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/referToUnderlyingPropertyInsideInlineClass.kt");
doTest(fileName);
}
@TestMetadata("referToUnderlyingPropertyOfInlineClass.kt")
public void testReferToUnderlyingPropertyOfInlineClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/referToUnderlyingPropertyOfInlineClass.kt");
doTest(fileName);
}
@TestMetadata("UIntArraySortExample.kt")
public void testUIntArraySortExample() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/UIntArraySortExample.kt");
@@ -10467,6 +10467,18 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
doTest(fileName);
}
@TestMetadata("referToUnderlyingPropertyInsideInlineClass.kt")
public void testReferToUnderlyingPropertyInsideInlineClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/referToUnderlyingPropertyInsideInlineClass.kt");
doTest(fileName);
}
@TestMetadata("referToUnderlyingPropertyOfInlineClass.kt")
public void testReferToUnderlyingPropertyOfInlineClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/referToUnderlyingPropertyOfInlineClass.kt");
doTest(fileName);
}
@TestMetadata("UIntArraySortExample.kt")
public void testUIntArraySortExample() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/UIntArraySortExample.kt");
@@ -1974,6 +1974,12 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
doTest(fileName);
}
@TestMetadata("skipCallToUnderlyingValueOfInlineClass.kt")
public void testSkipCallToUnderlyingValueOfInlineClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/inlineClasses/skipCallToUnderlyingValueOfInlineClass.kt");
doTest(fileName);
}
@TestMetadata("uIntArrayIteratorWithoutBoxing.kt")
public void testUIntArrayIteratorWithoutBoxing() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/inlineClasses/uIntArrayIteratorWithoutBoxing.kt");
@@ -10467,6 +10467,18 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
doTest(fileName);
}
@TestMetadata("referToUnderlyingPropertyInsideInlineClass.kt")
public void testReferToUnderlyingPropertyInsideInlineClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/referToUnderlyingPropertyInsideInlineClass.kt");
doTest(fileName);
}
@TestMetadata("referToUnderlyingPropertyOfInlineClass.kt")
public void testReferToUnderlyingPropertyOfInlineClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/referToUnderlyingPropertyOfInlineClass.kt");
doTest(fileName);
}
@TestMetadata("UIntArraySortExample.kt")
public void testUIntArraySortExample() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/UIntArraySortExample.kt");
@@ -11451,6 +11451,18 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
doTest(fileName);
}
@TestMetadata("referToUnderlyingPropertyInsideInlineClass.kt")
public void testReferToUnderlyingPropertyInsideInlineClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/referToUnderlyingPropertyInsideInlineClass.kt");
doTest(fileName);
}
@TestMetadata("referToUnderlyingPropertyOfInlineClass.kt")
public void testReferToUnderlyingPropertyOfInlineClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/referToUnderlyingPropertyOfInlineClass.kt");
doTest(fileName);
}
@TestMetadata("UIntArraySortExample.kt")
public void testUIntArraySortExample() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/UIntArraySortExample.kt");