Support references to extension properties in JVM codegen

#KT-1183 In Progress
This commit is contained in:
Alexander Udalov
2014-05-27 21:28:06 +04:00
parent 461cce103b
commit 5ab83aad8a
12 changed files with 140 additions and 16 deletions
@@ -785,4 +785,12 @@ public class AsmUtil {
return PackagePartClassUtils.getPackagePartInternalName(containingFile);
}
public static void putJavaLangClassInstance(@NotNull InstructionAdapter v, @NotNull Type type) {
if (isPrimitive(type)) {
v.getstatic(boxType(type).getInternalName(), "TYPE", "Ljava/lang/Class;");
}
else {
v.aconst(type);
}
}
}
@@ -2426,6 +2426,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
if (variableDescriptor != null) {
VariableDescriptor descriptor = (VariableDescriptor) resolvedCall.getResultingDescriptor();
ReceiverParameterDescriptor receiverParameter = descriptor.getReceiverParameter();
String reflectionFieldOwner;
Type propertyType;
Type ownerType;
@@ -2436,7 +2438,13 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
reflectionFieldOwner =
PackageClassUtils.getPackageClassInternalName(((PackageFragmentDescriptor) containingDeclaration).getFqName());
propertyType = descriptor.isVar() ? K_MUTABLE_TOP_LEVEL_PROPERTY_IMPL_TYPE : K_TOP_LEVEL_PROPERTY_IMPL_TYPE;
if (receiverParameter != null) {
propertyType = descriptor.isVar() ? K_MUTABLE_EXTENSION_PROPERTY_IMPL_TYPE : K_EXTENSION_PROPERTY_IMPL_TYPE;
}
else {
propertyType = descriptor.isVar() ? K_MUTABLE_TOP_LEVEL_PROPERTY_IMPL_TYPE : K_TOP_LEVEL_PROPERTY_IMPL_TYPE;
}
ownerType = K_PACKAGE_IMPL_TYPE;
reflectionFieldName = JvmAbi.KOTLIN_PACKAGE_FIELD_NAME;
}
@@ -2455,8 +2463,16 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
v.visitLdcInsn(descriptor.getName().asString());
v.getstatic(reflectionFieldOwner, reflectionFieldName, ownerType.getDescriptor());
v.invokespecial(propertyType.getInternalName(), "<init>",
Type.getMethodDescriptor(Type.VOID_TYPE, JAVA_STRING_TYPE, ownerType), false);
String constructorDesc;
if (receiverParameter != null) {
putJavaLangClassInstance(v, typeMapper.mapType(receiverParameter));
constructorDesc = Type.getMethodDescriptor(Type.VOID_TYPE, JAVA_STRING_TYPE, ownerType, getType(Class.class));
}
else {
constructorDesc = Type.getMethodDescriptor(Type.VOID_TYPE, JAVA_STRING_TYPE, ownerType);
}
v.invokespecial(propertyType.getInternalName(), "<init>", constructorDesc, false);
return StackValue.onStack(propertyType);
}
@@ -19,8 +19,6 @@ package org.jetbrains.jet.codegen.intrinsics;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.org.objectweb.asm.Type;
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
import org.jetbrains.jet.codegen.ExpressionCodegen;
import org.jetbrains.jet.codegen.StackValue;
import org.jetbrains.jet.lang.psi.JetCallExpression;
@@ -28,11 +26,12 @@ import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.org.objectweb.asm.Type;
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
import java.util.List;
import static org.jetbrains.jet.codegen.AsmUtil.boxType;
import static org.jetbrains.jet.codegen.AsmUtil.isPrimitive;
import static org.jetbrains.jet.codegen.AsmUtil.putJavaLangClassInstance;
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.getType;
public class JavaClassFunction extends IntrinsicMethod {
@@ -51,13 +50,7 @@ public class JavaClassFunction extends IntrinsicMethod {
assert resolvedCall != null;
JetType returnType = resolvedCall.getResultingDescriptor().getReturnType();
assert returnType != null;
Type type = codegen.getState().getTypeMapper().mapType(returnType.getArguments().get(0).getType());
if (isPrimitive(type)) {
v.getstatic(boxType(type).getInternalName(), "TYPE", "Ljava/lang/Class;");
}
else {
v.aconst(type);
}
putJavaLangClassInstance(v, codegen.getState().getTypeMapper().mapType(returnType.getArguments().get(0).getType()));
return getType(Class.class);
}
@@ -44,6 +44,8 @@ public class AsmTypeConstants {
public static final Type K_MUTABLE_TOP_LEVEL_PROPERTY_IMPL_TYPE = reflectInternal("KMutableTopLevelPropertyImpl");
public static final Type K_MEMBER_PROPERTY_IMPL_TYPE = reflectInternal("KMemberPropertyImpl");
public static final Type K_MUTABLE_MEMBER_PROPERTY_IMPL_TYPE = reflectInternal("KMutableMemberPropertyImpl");
public static final Type K_EXTENSION_PROPERTY_IMPL_TYPE = reflectInternal("KExtensionPropertyImpl");
public static final Type K_MUTABLE_EXTENSION_PROPERTY_IMPL_TYPE = reflectInternal("KMutableExtensionPropertyImpl");
public static final Type OBJECT_REF_TYPE = Type.getObjectType("kotlin/jvm/internal/Ref$ObjectRef");
@@ -0,0 +1,12 @@
val String.id: String
get() = this
fun box(): String {
val pr = String::id
if (pr["123"] != "123") return "Fail value: ${pr["123"]}"
if (pr.name != "id") return "Fail name: ${pr.name}"
return pr.get("OK")
}
@@ -0,0 +1,18 @@
var storage = 0
var Int.foo: Int
get() {
return this + storage
}
set(value) {
storage = this + value
}
fun box(): String {
val pr = Int::foo
if (pr.get(42) != 42) return "Fail 1: ${pr[42]}"
pr.set(200, 39)
if (pr.get(-239) != 0) return "Fail 2: ${pr[-239]}"
if (storage != 239) return "Fail 3: $storage"
return "OK"
}
@@ -0,0 +1,6 @@
package a
public var topLevel: Int = 42
public val String.extension: Long
get() = length.toLong()
@@ -0,0 +1,14 @@
import a.*
fun main(args: Array<String>) {
val f = ::topLevel
val x1 = f.get()
if (x1 != 42) throw AssertionError("Fail x1: $x1")
f.set(239)
val x2 = f.get()
if (x2 != 239) throw AssertionError("Fail x2: $x2")
val g = String::extension
val y1 = g.get("abcde")
if (y1 != 5L) throw AssertionError("Fail y1: $y1")
}
@@ -464,6 +464,11 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode
doTestWithStdlib("compiler/testData/codegen/boxWithStdlib/callableReference/property/simpleMember.kt");
}
@TestMetadata("simpleMutableExtension.kt")
public void testSimpleMutableExtension() throws Exception {
doTestWithStdlib("compiler/testData/codegen/boxWithStdlib/callableReference/property/simpleMutableExtension.kt");
}
@TestMetadata("simpleMutableMember.kt")
public void testSimpleMutableMember() throws Exception {
doTestWithStdlib("compiler/testData/codegen/boxWithStdlib/callableReference/property/simpleMutableMember.kt");
@@ -28,6 +28,7 @@ import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment;
import org.jetbrains.jet.codegen.ClassFileFactory;
import org.jetbrains.jet.codegen.GenerationUtils;
import org.jetbrains.jet.codegen.InlineTestUtil;
import org.jetbrains.jet.codegen.forTestCompile.ForTestCompileRuntime;
import org.jetbrains.jet.config.CompilerConfiguration;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.java.PackageClassUtils;
@@ -108,7 +109,7 @@ public abstract class AbstractCompileKotlinAgainstKotlinTest extends TestCaseWit
private void invokeMain() throws Exception {
URLClassLoader classLoader = new URLClassLoader(
new URL[]{ aDir.toURI().toURL(), bDir.toURI().toURL() },
new URL[]{ aDir.toURI().toURL(), bDir.toURI().toURL(), ForTestCompileRuntime.runtimeJarForTests().toURI().toURL() },
AbstractCompileKotlinAgainstKotlinTest.class.getClassLoader()
);
Class<?> clazz = classLoader.loadClass(PackageClassUtils.getPackageClassName(FqName.ROOT));
@@ -118,7 +119,7 @@ public abstract class AbstractCompileKotlinAgainstKotlinTest extends TestCaseWit
private void invokeBox() throws Exception {
URLClassLoader classLoader = new URLClassLoader(
new URL[]{ bDir.toURI().toURL(), aDir.toURI().toURL() },
new URL[]{ bDir.toURI().toURL(), aDir.toURI().toURL(), ForTestCompileRuntime.runtimeJarForTests().toURI().toURL() },
AbstractCompileKotlinAgainstKotlinTest.class.getClassLoader()
);
Class<?> clazz = classLoader.loadClass(PackageClassUtils.getPackageClassName(FqName.ROOT));
@@ -106,6 +106,11 @@ public class CompileKotlinAgainstKotlinTestGenerated extends AbstractCompileKotl
doTest("compiler/testData/compileKotlinAgainstKotlin/PlatformNames.A.kt");
}
@TestMetadata("PropertyReference.A.kt")
public void testPropertyReference() throws Exception {
doTest("compiler/testData/compileKotlinAgainstKotlin/PropertyReference.A.kt");
}
@TestMetadata("Simple.A.kt")
public void testSimple() throws Exception {
doTest("compiler/testData/compileKotlinAgainstKotlin/Simple.A.kt");