Inline static fields from Java
This commit is contained in:
@@ -28,11 +28,13 @@ import org.jetbrains.kotlin.codegen.state.GenerationState;
|
|||||||
import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
|
import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
|
||||||
import org.jetbrains.kotlin.descriptors.*;
|
import org.jetbrains.kotlin.descriptors.*;
|
||||||
import org.jetbrains.kotlin.load.java.JvmAbi;
|
import org.jetbrains.kotlin.load.java.JvmAbi;
|
||||||
|
import org.jetbrains.kotlin.load.java.descriptors.JavaPropertyDescriptor;
|
||||||
import org.jetbrains.kotlin.psi.JetExpression;
|
import org.jetbrains.kotlin.psi.JetExpression;
|
||||||
import org.jetbrains.kotlin.resolve.ImportedFromObjectCallableDescriptor;
|
import org.jetbrains.kotlin.resolve.ImportedFromObjectCallableDescriptor;
|
||||||
import org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt;
|
import org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt;
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument;
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument;
|
||||||
|
import org.jetbrains.kotlin.resolve.constants.ConstantValue;
|
||||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes;
|
import org.jetbrains.kotlin.resolve.jvm.AsmTypes;
|
||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind;
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind;
|
||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature;
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature;
|
||||||
@@ -1040,7 +1042,10 @@ public abstract class StackValue {
|
|||||||
if (getter == null) {
|
if (getter == null) {
|
||||||
assert fieldName != null : "Property should have either a getter or a field name: " + descriptor;
|
assert fieldName != null : "Property should have either a getter or a field name: " + descriptor;
|
||||||
assert backingFieldOwner != null : "Property should have either a getter or a backingFieldOwner: " + descriptor;
|
assert backingFieldOwner != null : "Property should have either a getter or a backingFieldOwner: " + descriptor;
|
||||||
v.visitFieldInsn(isStaticPut ? GETSTATIC : GETFIELD, backingFieldOwner.getInternalName(), fieldName, this.type.getDescriptor());
|
if (inlineJavaConstantIfNeeded(type, v)) return;
|
||||||
|
|
||||||
|
v.visitFieldInsn(isStaticPut ? GETSTATIC : GETFIELD,
|
||||||
|
backingFieldOwner.getInternalName(), fieldName, this.type.getDescriptor());
|
||||||
if (!genNotNullAssertionForField(v, state, descriptor)) {
|
if (!genNotNullAssertionForField(v, state, descriptor)) {
|
||||||
genNotNullAssertionForLateInitIfNeeded(v);
|
genNotNullAssertionForLateInitIfNeeded(v);
|
||||||
}
|
}
|
||||||
@@ -1052,6 +1057,25 @@ public abstract class StackValue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean inlineJavaConstantIfNeeded(@NotNull Type type, @NotNull InstructionAdapter v) {
|
||||||
|
if (!isStaticPut) return false;
|
||||||
|
if (!(descriptor instanceof JavaPropertyDescriptor)) return false;
|
||||||
|
if (!AsmUtil.isPrimitive(this.type) && !this.type.equals(Type.getObjectType("java/lang/String"))) return false;
|
||||||
|
|
||||||
|
JavaPropertyDescriptor javaPropertyDescriptor = (JavaPropertyDescriptor) descriptor;
|
||||||
|
ConstantValue<?> constantValue = javaPropertyDescriptor.getCompileTimeInitializer();
|
||||||
|
if (constantValue == null) return false;
|
||||||
|
|
||||||
|
Object value = constantValue.getValue();
|
||||||
|
if (this.type == Type.FLOAT_TYPE && value instanceof Double) {
|
||||||
|
value = ((Double) value).floatValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
new Constant(value, this.type).putSelector(type, v);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private void genNotNullAssertionForLateInitIfNeeded(@NotNull InstructionAdapter v) {
|
private void genNotNullAssertionForLateInitIfNeeded(@NotNull InstructionAdapter v) {
|
||||||
if (!descriptor.isLateInit()) return;
|
if (!descriptor.isLateInit()) return;
|
||||||
|
|
||||||
|
|||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public class JClass {
|
||||||
|
public final static int PrimitiveInt = 9000;
|
||||||
|
public final static int BigPrimitiveInt = 59000;
|
||||||
|
public final static long PrimitiveLong = 100000;
|
||||||
|
public final static short PrimitiveShort = 900;
|
||||||
|
public final static boolean PrimitiveBool = false;
|
||||||
|
public final static float PrimitiveFloat = 36.6;
|
||||||
|
public final static double PrimitiveDouble = 42.4242;
|
||||||
|
public final static byte PrimitiveByte = -8;
|
||||||
|
public final static char PrimitiveChar = 'K';
|
||||||
|
public final static String Str = ":J";
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public final static Integer BoxedInt = 9500;
|
||||||
|
|
||||||
|
public static int NonFinal = 9700;
|
||||||
|
|
||||||
|
public final int NonStatic = 9800;
|
||||||
|
}
|
||||||
+47
@@ -0,0 +1,47 @@
|
|||||||
|
object KoKobject {
|
||||||
|
@JvmStatic
|
||||||
|
val JvmStatic: Int = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
Integer.MIN_VALUE
|
||||||
|
java.lang.Long.MAX_VALUE
|
||||||
|
|
||||||
|
JClass.PrimitiveInt
|
||||||
|
JClass.BigPrimitiveInt
|
||||||
|
JClass.PrimitiveByte
|
||||||
|
JClass.PrimitiveChar
|
||||||
|
JClass.PrimitiveLong
|
||||||
|
JClass.PrimitiveShort
|
||||||
|
JClass.PrimitiveBool
|
||||||
|
JClass.PrimitiveFloat
|
||||||
|
JClass.PrimitiveDouble
|
||||||
|
JClass.Str
|
||||||
|
|
||||||
|
JClass.BoxedInt
|
||||||
|
JClass.NonFinal
|
||||||
|
|
||||||
|
JClass().NonStatic
|
||||||
|
|
||||||
|
KoKobject.JvmStatic
|
||||||
|
}
|
||||||
|
|
||||||
|
// @TestKt.class:
|
||||||
|
// 1 LDC -2147483648
|
||||||
|
// 1 LDC 9223372036854775807
|
||||||
|
// 1 SIPUSH 9000
|
||||||
|
// 1 LDC 59000
|
||||||
|
// 1 LDC -8
|
||||||
|
// 1 LDC K
|
||||||
|
// 1 LDC 100000
|
||||||
|
// 1 LDC 900
|
||||||
|
// 1 LDC false
|
||||||
|
// 1 LDC 36.6
|
||||||
|
// 1 LDC 42.4242
|
||||||
|
// 1 LDC ":J"
|
||||||
|
// 1 GETSTATIC JClass.BoxedInt : Ljava/lang/Integer;
|
||||||
|
// 1 GETSTATIC JClass.NonFinal : I
|
||||||
|
// 1 GETFIELD JClass.NonStatic : I
|
||||||
|
// 1 INVOKESTATIC KoKobject.getJvmStatic \(\)I
|
||||||
|
// 3 POP2
|
||||||
|
// 16 POP
|
||||||
@@ -35,6 +35,12 @@ public class BytecodeTextMultifileTestGenerated extends AbstractBytecodeTextTest
|
|||||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/bytecodeTextMultifile"), Pattern.compile("^([^\\.]+)$"), false);
|
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/bytecodeTextMultifile"), Pattern.compile("^([^\\.]+)$"), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("inlineJavaStaticFields")
|
||||||
|
public void testInlineJavaStaticFields() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeTextMultifile/inlineJavaStaticFields/");
|
||||||
|
doTestMultiFile(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("javaStatics")
|
@TestMetadata("javaStatics")
|
||||||
public void testJavaStatics() throws Exception {
|
public void testJavaStatics() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeTextMultifile/javaStatics/");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeTextMultifile/javaStatics/");
|
||||||
|
|||||||
Reference in New Issue
Block a user