Don't create KClass and KPackage instances in <clinit>
This proved to be a fragile technique, which probably doesn't even improve performance in most cases but has lots of unexpected problems: unconditional initialization of reflection classes, increasing the size of the bytecode, bugs with <clinit> in annotations on JVM 6, inability to support conversion of a class from Kotlin to Java without recompiling clients which use it reflectively, etc.
This commit is contained in:
@@ -314,7 +314,7 @@ public class ClosureCodegen extends MemberCodegen<JetElement> {
|
||||
if (generateBody) {
|
||||
mv.visitCode();
|
||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
generateCallableReferenceDeclarationContainer(iv, descriptor, typeMapper);
|
||||
generateCallableReferenceDeclarationContainer(iv, descriptor, state);
|
||||
iv.areturn(K_DECLARATION_CONTAINER_TYPE);
|
||||
FunctionCodegen.endVisit(iv, "function reference getOwner", element);
|
||||
}
|
||||
@@ -348,24 +348,28 @@ public class ClosureCodegen extends MemberCodegen<JetElement> {
|
||||
public static void generateCallableReferenceDeclarationContainer(
|
||||
@NotNull InstructionAdapter iv,
|
||||
@NotNull CallableDescriptor descriptor,
|
||||
@NotNull JetTypeMapper typeMapper
|
||||
@NotNull GenerationState state
|
||||
) {
|
||||
DeclarationDescriptor container = descriptor.getContainingDeclaration();
|
||||
if (container instanceof ClassDescriptor) {
|
||||
// TODO: getDefaultType() here is wrong and won't work for arrays
|
||||
StackValue value = generateClassLiteralReference(typeMapper, ((ClassDescriptor) container).getDefaultType());
|
||||
StackValue value = generateClassLiteralReference(state.getTypeMapper(), ((ClassDescriptor) container).getDefaultType());
|
||||
value.put(K_CLASS_TYPE, iv);
|
||||
}
|
||||
else if (container instanceof PackageFragmentDescriptor) {
|
||||
String packageClassInternalName = PackageClassUtils.getPackageClassInternalName(
|
||||
((PackageFragmentDescriptor) container).getFqName()
|
||||
);
|
||||
iv.getstatic(packageClassInternalName, JvmAbi.KOTLIN_PACKAGE_FIELD_NAME, K_PACKAGE_TYPE.getDescriptor());
|
||||
iv.aconst(Type.getObjectType(packageClassInternalName));
|
||||
iv.aconst(state.getModuleName());
|
||||
// TODO: create KPackage with a useful class, not the old package facade
|
||||
iv.invokestatic(REFLECTION, "createKotlinPackage",
|
||||
Type.getMethodDescriptor(K_PACKAGE_TYPE, getType(Class.class), getType(String.class)), false);
|
||||
}
|
||||
else if (container instanceof ScriptDescriptor) {
|
||||
// TODO: correct container for scripts (KScript?)
|
||||
StackValue value = generateClassLiteralReference(
|
||||
typeMapper, ((ScriptDescriptor) container).getClassDescriptor().getDefaultType()
|
||||
state.getTypeMapper(), ((ScriptDescriptor) container).getClassDescriptor().getDefaultType()
|
||||
);
|
||||
value.put(K_CLASS_TYPE, iv);
|
||||
}
|
||||
|
||||
@@ -36,7 +36,10 @@ import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
|
||||
import org.jetbrains.kotlin.codegen.context.*;
|
||||
import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension;
|
||||
import org.jetbrains.kotlin.codegen.inline.*;
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.*;
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethod;
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods;
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicPropertyGetter;
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.TypeIntrinsics;
|
||||
import org.jetbrains.kotlin.codegen.pseudoInsns.PseudoInsnsPackage;
|
||||
import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
@@ -90,7 +93,8 @@ import java.util.*;
|
||||
|
||||
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.isInt;
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.*;
|
||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.*;
|
||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.couldUseDirectAccessToProperty;
|
||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isJvmInterface;
|
||||
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.*;
|
||||
import static org.jetbrains.kotlin.psi.PsiPackage.JetPsiFactory;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContext.*;
|
||||
@@ -2806,30 +2810,18 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor();
|
||||
if (descriptor instanceof TypeParameterDescriptor) {
|
||||
TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) descriptor;
|
||||
if (typeParameterDescriptor.isReified()) {
|
||||
// Emit reified type parameters as Kotlin classes.
|
||||
// ReifiedTypeInliner will rewrite the following GETSTATIC to proper bytecode instructions
|
||||
// if the class literal for actual type should be emitted with wrapped Java class.
|
||||
v.visitLdcInsn(typeParameterDescriptor.getName().asString());
|
||||
v.invokestatic(
|
||||
IntrinsicMethods.INTRINSICS_CLASS_NAME, ReifiedTypeInliner.CLASS_LITERAL_MARKER_METHOD_NAME,
|
||||
Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(String.class)), false
|
||||
);
|
||||
v.getstatic(classAsmType.getInternalName(), JvmAbi.KOTLIN_CLASS_FIELD_NAME, K_CLASS_TYPE.getDescriptor());
|
||||
}
|
||||
else {
|
||||
throw new AssertionError("Non-reified type parameter under ::class should be rejected by type checker: " +
|
||||
typeParameterDescriptor.getName().asString());
|
||||
}
|
||||
}
|
||||
else if (shouldUseJavaClassForClassLiteral(descriptor)) {
|
||||
putJavaLangClassInstance(v, classAsmType);
|
||||
wrapJavaClassIntoKClass(v);
|
||||
}
|
||||
else {
|
||||
v.getstatic(classAsmType.getInternalName(), JvmAbi.KOTLIN_CLASS_FIELD_NAME, K_CLASS_TYPE.getDescriptor());
|
||||
assert typeParameterDescriptor.isReified() :
|
||||
"Non-reified type parameter under ::class should be rejected by type checker: " + typeParameterDescriptor;
|
||||
v.visitLdcInsn(typeParameterDescriptor.getName().asString());
|
||||
v.invokestatic(
|
||||
IntrinsicMethods.INTRINSICS_CLASS_NAME, ReifiedTypeInliner.JAVA_CLASS_MARKER_METHOD_NAME,
|
||||
Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(String.class)), false
|
||||
);
|
||||
}
|
||||
|
||||
putJavaLangClassInstance(v, classAsmType);
|
||||
wrapJavaClassIntoKClass(v);
|
||||
|
||||
return Unit.INSTANCE$;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -86,7 +86,8 @@ import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
|
||||
import static org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage.getResolvedCall;
|
||||
import static org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilPackage.getBuiltIns;
|
||||
import static org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilPackage.getSecondaryConstructors;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.*;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.JAVA_STRING_TYPE;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.diagnostics.DiagnosticsPackage.*;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.NO_ORIGIN;
|
||||
import static org.jetbrains.kotlin.types.Variance.INVARIANT;
|
||||
@@ -227,8 +228,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
AnnotationCodegen.forClass(v.getVisitor(), typeMapper).genAnnotations(descriptor, null);
|
||||
|
||||
generateReflectionObjectFieldIfNeeded();
|
||||
|
||||
generateEnumEntries();
|
||||
}
|
||||
|
||||
@@ -413,18 +412,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
private void generateReflectionObjectFieldIfNeeded() {
|
||||
if (isAnnotationClass(descriptor)) {
|
||||
// There's a bug in JDK 6 and 7 that prevents us from generating a static field in an annotation class:
|
||||
// http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6857918
|
||||
// TODO: make reflection work on annotation classes somehow
|
||||
return;
|
||||
}
|
||||
|
||||
generateReflectionObjectField(state, classAsmType, v, method("createKotlinClass", K_CLASS_TYPE, getType(Class.class)),
|
||||
JvmAbi.KOTLIN_CLASS_FIELD_NAME, createOrGetClInitCodegen().v);
|
||||
}
|
||||
|
||||
private boolean isGenericToArrayPresent() {
|
||||
Collection<FunctionDescriptor> functions =
|
||||
descriptor.getDefaultType().getMemberScope().getFunctions(Name.identifier("toArray"), NoLookupLocation.FROM_BACKEND);
|
||||
|
||||
@@ -31,7 +31,6 @@ import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi;
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames;
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor;
|
||||
import org.jetbrains.kotlin.load.kotlin.ModuleMapping;
|
||||
import org.jetbrains.kotlin.load.kotlin.ModuleVisibilityUtilsKt;
|
||||
import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils;
|
||||
@@ -212,13 +211,6 @@ public class JvmCodegenUtil {
|
||||
InlineUtil.isInlinedArgument((JetFunction) declaration, bindingContext, false);
|
||||
}
|
||||
|
||||
public static boolean shouldUseJavaClassForClassLiteral(@NotNull ClassifierDescriptor descriptor) {
|
||||
ModuleDescriptor module = DescriptorUtils.getContainingModule(descriptor);
|
||||
return descriptor instanceof JavaClassDescriptor ||
|
||||
module == module.getBuiltIns().getBuiltInsModule() ||
|
||||
DescriptorUtils.isAnnotationClass(descriptor);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String getModuleName(ModuleDescriptor module) {
|
||||
return StringsKt.removeSurrounding(module.getName().asString(), "<", ">");
|
||||
|
||||
@@ -29,7 +29,6 @@ import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils
|
||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
|
||||
import org.jetbrains.kotlin.fileClasses.getFileClassType
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
|
||||
import org.jetbrains.kotlin.load.kotlin.PackageParts
|
||||
import org.jetbrains.kotlin.load.kotlin.incremental.IncrementalPackageFragmentProvider
|
||||
@@ -38,9 +37,7 @@ import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStat
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.MemberComparator
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.MultifileClass
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.MultifileClassPart
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin
|
||||
@@ -53,7 +50,6 @@ import org.jetbrains.kotlin.serialization.deserialization.descriptors.Deserializ
|
||||
import org.jetbrains.org.objectweb.asm.MethodVisitor
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
import java.util.*
|
||||
|
||||
public class MultifileClassCodegen(
|
||||
@@ -141,7 +137,6 @@ public class MultifileClassCodegen(
|
||||
tasks: Map<CallableMemberDescriptor, () -> Unit>,
|
||||
partFqNames: List<FqName>
|
||||
) {
|
||||
generateKotlinPackageReflectionField()
|
||||
MemberCodegen.generateModuleNameField(state, classBuilder)
|
||||
|
||||
for (member in tasks.keySet().sortedWith(MemberComparator.INSTANCE)) {
|
||||
@@ -261,16 +256,6 @@ public class MultifileClassCodegen(
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateKotlinPackageReflectionField() {
|
||||
val mv = classBuilder.newMethod(JvmDeclarationOrigin.NO_ORIGIN, Opcodes.ACC_STATIC, "<clinit>", "()V", null, null)
|
||||
val method = AsmUtil.method("createKotlinPackage",
|
||||
AsmTypes.K_PACKAGE_TYPE, AsmTypes.getType(Class::class.java), AsmTypes.getType(String::class.java))
|
||||
val iv = InstructionAdapter(mv)
|
||||
MemberCodegen.generateReflectionObjectField(state, facadeClassType, classBuilder, method, JvmAbi.KOTLIN_PACKAGE_FIELD_NAME, iv)
|
||||
iv.areturn(Type.VOID_TYPE)
|
||||
FunctionCodegen.endVisit(mv, "package facade static initializer", null)
|
||||
}
|
||||
|
||||
private fun writeKotlinMultifileFacadeAnnotationIfNeeded(partFqNames: List<FqName>) {
|
||||
if (state.classBuilderMode != ClassBuilderMode.FULL) return
|
||||
if (files.any { it.isScript }) return
|
||||
|
||||
@@ -43,7 +43,6 @@ import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor;
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils;
|
||||
import org.jetbrains.kotlin.fileClasses.FileClasses;
|
||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassInfo;
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi;
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames;
|
||||
import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils;
|
||||
import org.jetbrains.kotlin.load.kotlin.PackageParts;
|
||||
@@ -65,17 +64,11 @@ import org.jetbrains.kotlin.serialization.deserialization.descriptors.Deserializ
|
||||
import org.jetbrains.org.objectweb.asm.AnnotationVisitor;
|
||||
import org.jetbrains.org.objectweb.asm.MethodVisitor;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
|
||||
import org.jetbrains.org.objectweb.asm.commons.Method;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.asmDescByFqNameWithoutInnerClasses;
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.method;
|
||||
import static org.jetbrains.kotlin.load.kotlin.PackageClassUtils.getPackageClassFqName;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.K_PACKAGE_TYPE;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.getType;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.NO_ORIGIN;
|
||||
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
|
||||
|
||||
public class PackageCodegen {
|
||||
@@ -256,7 +249,6 @@ public class PackageCodegen {
|
||||
@NotNull Map<CallableMemberDescriptor, Runnable> tasks,
|
||||
@NotNull List<JvmSerializationBindings> bindings
|
||||
) {
|
||||
generateKotlinPackageReflectionField();
|
||||
MemberCodegen.generateModuleNameField(state, v);
|
||||
|
||||
for (CallableMemberDescriptor member : Ordering.from(MemberComparator.INSTANCE).sortedCopy(tasks.keySet())) {
|
||||
@@ -268,15 +260,6 @@ public class PackageCodegen {
|
||||
writeKotlinPackageAnnotationIfNeeded(JvmSerializationBindings.union(bindings));
|
||||
}
|
||||
|
||||
private void generateKotlinPackageReflectionField() {
|
||||
MethodVisitor mv = v.newMethod(NO_ORIGIN, ACC_STATIC, "<clinit>", "()V", null, null);
|
||||
Method method = method("createKotlinPackage", K_PACKAGE_TYPE, getType(Class.class), getType(String.class));
|
||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
MemberCodegen.generateReflectionObjectField(state, packageClassType, v, method, JvmAbi.KOTLIN_PACKAGE_FIELD_NAME, iv);
|
||||
iv.areturn(Type.VOID_TYPE);
|
||||
FunctionCodegen.endVisit(mv, "package facade static initializer", null);
|
||||
}
|
||||
|
||||
private void writeKotlinPackageAnnotationIfNeeded(@NotNull JvmSerializationBindings bindings) {
|
||||
if (state.getClassBuilderMode() != ClassBuilderMode.FULL) {
|
||||
return;
|
||||
|
||||
@@ -103,7 +103,7 @@ public class PropertyReferenceCodegen(
|
||||
}
|
||||
|
||||
generateMethod("property reference getOwner", ACC_PUBLIC, method("getOwner", K_DECLARATION_CONTAINER_TYPE)) {
|
||||
ClosureCodegen.generateCallableReferenceDeclarationContainer(this, target, typeMapper)
|
||||
ClosureCodegen.generateCallableReferenceDeclarationContainer(this, target, state)
|
||||
}
|
||||
|
||||
generateMethod("property reference getName", ACC_PUBLIC, method("getName", JAVA_STRING_TYPE)) {
|
||||
|
||||
@@ -27,7 +27,6 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.ScriptDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor;
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
|
||||
@@ -38,10 +37,9 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.method;
|
||||
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.CLASS_FOR_SCRIPT;
|
||||
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.asmTypeForScriptDescriptor;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.*;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.diagnostics.DiagnosticsPackage.OtherOrigin;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.NO_ORIGIN;
|
||||
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
|
||||
@@ -101,9 +99,6 @@ public class ScriptCodegen extends MemberCodegen<JetScript> {
|
||||
null,
|
||||
"java/lang/Object",
|
||||
ArrayUtil.EMPTY_STRING_ARRAY);
|
||||
|
||||
generateReflectionObjectField(state, classType, v, method("createKotlinClass", K_CLASS_TYPE, getType(Class.class)),
|
||||
JvmAbi.KOTLIN_CLASS_FIELD_NAME, createOrGetClInitCodegen().v);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -27,7 +27,9 @@ import org.jetbrains.annotations.TestOnly;
|
||||
import org.jetbrains.kotlin.backend.common.output.OutputFile;
|
||||
import org.jetbrains.kotlin.codegen.MemberCodegen;
|
||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
|
||||
import org.jetbrains.kotlin.codegen.context.*;
|
||||
import org.jetbrains.kotlin.codegen.context.CodegenContext;
|
||||
import org.jetbrains.kotlin.codegen.context.CodegenContextUtil;
|
||||
import org.jetbrains.kotlin.codegen.context.MethodContext;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
@@ -298,7 +300,7 @@ public class InlineCodegenUtil {
|
||||
|
||||
public static boolean isCapturedFieldName(@NotNull String fieldName) {
|
||||
// TODO: improve this heuristic
|
||||
return (fieldName.startsWith(CAPTURED_FIELD_PREFIX) && !fieldName.equals(JvmAbi.KOTLIN_CLASS_FIELD_NAME)) ||
|
||||
return fieldName.startsWith(CAPTURED_FIELD_PREFIX) ||
|
||||
THIS$0.equals(fieldName) ||
|
||||
RECEIVER$0.equals(fieldName);
|
||||
}
|
||||
|
||||
@@ -17,13 +17,10 @@
|
||||
package org.jetbrains.kotlin.codegen.inline
|
||||
|
||||
import com.google.common.collect.ImmutableSet
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil
|
||||
import org.jetbrains.kotlin.codegen.JvmCodegenUtil
|
||||
import org.jetbrains.kotlin.codegen.context.MethodContext
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.TypeIntrinsics
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
import org.jetbrains.kotlin.types.JetType
|
||||
import org.jetbrains.org.objectweb.asm.MethodVisitor
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
@@ -40,14 +37,12 @@ public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParame
|
||||
public val SAFE_CHECKCAST_MARKER_METHOD_NAME: String = "reifySafeCheckcast"
|
||||
public val INSTANCEOF_MARKER_METHOD_NAME: String = "reifyInstanceof"
|
||||
public val JAVA_CLASS_MARKER_METHOD_NAME: String = "reifyJavaClass"
|
||||
public val CLASS_LITERAL_MARKER_METHOD_NAME: String = "reifyClassLiteral"
|
||||
public val NEED_CLASS_REIFICATION_MARKER_METHOD_NAME: String = "needClassReification"
|
||||
|
||||
private val PARAMETRISED_MARKERS = ImmutableSet.of(
|
||||
NEW_ARRAY_MARKER_METHOD_NAME,
|
||||
CHECKCAST_MARKER_METHOD_NAME, SAFE_CHECKCAST_MARKER_METHOD_NAME,
|
||||
INSTANCEOF_MARKER_METHOD_NAME, JAVA_CLASS_MARKER_METHOD_NAME,
|
||||
CLASS_LITERAL_MARKER_METHOD_NAME
|
||||
INSTANCEOF_MARKER_METHOD_NAME, JAVA_CLASS_MARKER_METHOD_NAME
|
||||
)
|
||||
|
||||
private fun isParametrisedReifiedMarker(insn: AbstractInsnNode) =
|
||||
@@ -148,7 +143,6 @@ public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParame
|
||||
SAFE_CHECKCAST_MARKER_METHOD_NAME -> processCheckcast(insn, instructions, jetType, asmType, safe = true)
|
||||
INSTANCEOF_MARKER_METHOD_NAME -> processInstanceof(insn, instructions, jetType, asmType)
|
||||
JAVA_CLASS_MARKER_METHOD_NAME -> processJavaClass(insn, asmType)
|
||||
CLASS_LITERAL_MARKER_METHOD_NAME -> processClassLiteral(insn, instructions, jetType, asmType)
|
||||
else -> false
|
||||
}) {
|
||||
instructions.remove(insn.getPrevious()!!)
|
||||
@@ -202,30 +196,6 @@ public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParame
|
||||
return true
|
||||
}
|
||||
|
||||
private fun processClassLiteral(insn: MethodInsnNode, instructions: InsnList, type: JetType, parameter: Type): Boolean {
|
||||
val next = insn.next
|
||||
if (next !is FieldInsnNode || next.opcode != Opcodes.GETSTATIC) return false
|
||||
val descriptor = type.constructor.declarationDescriptor!!
|
||||
if (JvmCodegenUtil.shouldUseJavaClassForClassLiteral(descriptor)) {
|
||||
instructions.insertBefore(
|
||||
next,
|
||||
if (AsmUtil.isPrimitive(parameter))
|
||||
FieldInsnNode(Opcodes.GETSTATIC, AsmUtil.boxType(parameter).internalName, "TYPE", "Ljava/lang/Class;")
|
||||
else
|
||||
LdcInsnNode(parameter)
|
||||
)
|
||||
val foreignKotlinClassDesc = Type.getMethodDescriptor(AsmTypes.K_CLASS_TYPE, AsmTypes.JAVA_CLASS_TYPE)
|
||||
instructions.insertBefore(
|
||||
next, MethodInsnNode(Opcodes.INVOKESTATIC, AsmTypes.REFLECTION, "foreignKotlinClass", foreignKotlinClassDesc, false)
|
||||
)
|
||||
instructions.remove(next)
|
||||
}
|
||||
else {
|
||||
next.owner = AsmUtil.boxType(parameter).internalName
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun getParameterName(insn: MethodInsnNode): String? {
|
||||
val prev = insn.getPrevious()!!
|
||||
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
import kotlin.reflect.jvm.kotlin
|
||||
|
||||
class A {
|
||||
// There's a synthetic "$kotlinClass" field here
|
||||
enum class A {
|
||||
// There's a synthetic field "$VALUES" here
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
@kotlin.jvm.internal.KotlinClass Example {
|
||||
public synthetic field $kotlinClass: kotlin.reflect.KClass
|
||||
private synthetic @org.jetbrains.annotations.NotNull field prop: java.lang.String
|
||||
private field prop2: int
|
||||
private synthetic field useSite: int
|
||||
private field useSite2: int
|
||||
method <clinit>(): void
|
||||
public @org.jetbrains.annotations.NotNull method getProp(): java.lang.String
|
||||
public synthetic method getProp2(): int
|
||||
public synthetic method setProp2(p0: int): void
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
@kotlin.jvm.internal.KotlinClass A {
|
||||
public synthetic field $kotlinClass: kotlin.reflect.KClass
|
||||
private @AnnField @AnnParameterField @AnnTypeField field a: int
|
||||
private @AnnField @AnnTypeField field x: int
|
||||
method <clinit>(): void
|
||||
private synthetic deprecated @AnnProperty @AnnFieldProperty @AnnParameterProperty method a$annotations(): void
|
||||
public method getA(): int
|
||||
private synthetic deprecated @AnnProperty @AnnFieldProperty method x$annotations(): void
|
||||
@@ -20,4 +18,4 @@
|
||||
|
||||
@kotlin.annotation.Target @java.lang.annotation.Retention @java.lang.annotation.Target @kotlin.jvm.internal.KotlinClass AnnProperty
|
||||
|
||||
@kotlin.annotation.Target @java.lang.annotation.Retention @java.lang.annotation.Target @kotlin.jvm.internal.KotlinClass AnnTypeField
|
||||
@kotlin.annotation.Target @java.lang.annotation.Retention @java.lang.annotation.Target @kotlin.jvm.internal.KotlinClass AnnTypeField
|
||||
|
||||
@@ -22,8 +22,6 @@
|
||||
|
||||
@kotlin.jvm.internal.KotlinLocalClass @kotlin.jvm.internal.KotlinClass LiteralsKt$foo$3 {
|
||||
inner class LiteralsKt$foo$3
|
||||
public synthetic field $kotlinClass: kotlin.reflect.KClass
|
||||
method <clinit>(): void
|
||||
method <init>(): void
|
||||
}
|
||||
|
||||
@@ -45,15 +43,11 @@
|
||||
}
|
||||
|
||||
@kotlin.jvm.internal.KotlinClass My {
|
||||
public synthetic field $kotlinClass: kotlin.reflect.KClass
|
||||
method <clinit>(): void
|
||||
public method <init>(): void
|
||||
}
|
||||
|
||||
@java.lang.Deprecated @kotlin.jvm.internal.KotlinPackage _DefaultPackage {
|
||||
public synthetic field $kotlinPackage: kotlin.reflect.KPackage
|
||||
public synthetic field $moduleName: java.lang.String
|
||||
method <clinit>(): void
|
||||
public @kotlin.jvm.internal.KotlinDelegatedMethod method bar(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function0): int
|
||||
public @kotlin.jvm.internal.KotlinDelegatedMethod @org.jetbrains.annotations.NotNull method foo(p0: int): My
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
@kotlin.jvm.internal.KotlinClass A {
|
||||
public synthetic field $kotlinClass: kotlin.reflect.KClass
|
||||
private @AnnField field p: int
|
||||
private @AnnField field x: int
|
||||
private field y: int
|
||||
method <clinit>(): void
|
||||
private synthetic deprecated @AnnProp @AnnProp2 method p$annotations(): void
|
||||
public @AnnGetter method getP(): int
|
||||
public @AnnSetter method setP(@AnnParam p0: int): void
|
||||
@@ -24,4 +22,4 @@
|
||||
|
||||
@java.lang.annotation.Retention @kotlin.jvm.internal.KotlinClass AnnProp2
|
||||
|
||||
@java.lang.annotation.Retention @kotlin.jvm.internal.KotlinClass AnnSetter
|
||||
@java.lang.annotation.Retention @kotlin.jvm.internal.KotlinClass AnnSetter
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
@kotlin.jvm.internal.KotlinClass A {
|
||||
public synthetic field $kotlinClass: kotlin.reflect.KClass
|
||||
method <clinit>(): void
|
||||
public @org.jetbrains.annotations.NotNull method f(@Ann p0: java.lang.String): java.lang.String
|
||||
public @org.jetbrains.annotations.NotNull method getP(@Ann p0: java.lang.String): java.lang.String
|
||||
public method <init>(): void
|
||||
@@ -14,9 +12,7 @@
|
||||
}
|
||||
|
||||
@java.lang.Deprecated @kotlin.jvm.internal.KotlinPackage _DefaultPackage {
|
||||
public synthetic field $kotlinPackage: kotlin.reflect.KPackage
|
||||
public synthetic field $moduleName: java.lang.String
|
||||
method <clinit>(): void
|
||||
public @kotlin.jvm.internal.KotlinDelegatedMethod @org.jetbrains.annotations.NotNull method getTopLevelP(@Ann p0: java.lang.String): java.lang.String
|
||||
public @kotlin.jvm.internal.KotlinDelegatedMethod @org.jetbrains.annotations.NotNull method topLevelF(@Ann p0: java.lang.String): java.lang.String
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ fun box(): String {
|
||||
/*
|
||||
3 return's are defined in functions
|
||||
2 are from package facade
|
||||
1 is from package clinit
|
||||
*/
|
||||
|
||||
// 6 RETURN
|
||||
// 5 RETURN
|
||||
|
||||
@@ -22,7 +22,7 @@ import org.jetbrains.asm4.ClassVisitor
|
||||
import org.jetbrains.asm4.MethodVisitor
|
||||
import org.jetbrains.asm4.Opcodes
|
||||
import org.jetbrains.kotlin.test.ConfigurationKind
|
||||
import java.util.ArrayList
|
||||
import java.util.*
|
||||
|
||||
public class MethodOrderTest: CodegenTestCase() {
|
||||
public fun testDelegatedMethod() {
|
||||
@@ -44,7 +44,7 @@ public class MethodOrderTest: CodegenTestCase() {
|
||||
}
|
||||
""",
|
||||
"\$obj$1",
|
||||
listOf("<clinit>()V", "f3()V", "<init>()V", "f0()V", "f1()V", "f2()V", "f4()V", "f5()V")
|
||||
listOf("f3()V", "<init>()V", "f0()V", "f1()V", "f2()V", "f4()V", "f5()V")
|
||||
)
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ public class MethodOrderTest: CodegenTestCase() {
|
||||
}
|
||||
""",
|
||||
"\$f$1",
|
||||
listOf("<clinit>()V", "run()V", "<init>(LKlass;Ljava/lang/Object;Ljava/lang/String;IDLjava/lang/Object;J)V")
|
||||
listOf("run()V", "<init>(LKlass;Ljava/lang/Object;Ljava/lang/String;IDLjava/lang/Object;J)V")
|
||||
)
|
||||
}
|
||||
|
||||
@@ -97,7 +97,6 @@ public class MethodOrderTest: CodegenTestCase() {
|
||||
""",
|
||||
"Outer",
|
||||
listOf(
|
||||
"<clinit>()V",
|
||||
"c()V",
|
||||
"<init>(ILjava/lang/String;)V",
|
||||
"access\$getB$0(LOuter;)Ljava/lang/String;",
|
||||
|
||||
@@ -52,8 +52,6 @@ public final class JvmAbi {
|
||||
public static final String INSTANCE_FIELD = "INSTANCE";
|
||||
public static final String DEPRECATED_INSTANCE_FIELD = "INSTANCE$";
|
||||
|
||||
public static final String KOTLIN_CLASS_FIELD_NAME = "$kotlinClass";
|
||||
public static final String KOTLIN_PACKAGE_FIELD_NAME = "$kotlinPackage";
|
||||
public static final String MODULE_NAME_FIELD = "$moduleName";
|
||||
public static final String DEFAULT_MODULE_NAME = "main";
|
||||
public static final ClassId REFLECTION_FACTORY_IMPL = ClassId.topLevel(new FqName("kotlin.reflect.jvm.internal.ReflectionFactoryImpl"));
|
||||
|
||||
@@ -30,10 +30,10 @@ class MyDelegateThrowsException {
|
||||
local = args: java.lang.String[] = {java.lang.String[0]@uniqueID} (sp = delegatedPropertyInClass.kt, 5)
|
||||
local = a: delegatedPropertyInClass.A = {delegatedPropertyInClass.A@uniqueID} (sp = delegatedPropertyInClass.kt, 6)
|
||||
field = prop$delegate: delegatedPropertyInClass.MyDelegate = {delegatedPropertyInClass.MyDelegate@uniqueID} (sp = delegatedPropertyInClass.kt, 12)
|
||||
- No fields to display
|
||||
- Class has no fields
|
||||
field = prop: int = 1 (sp = delegatedPropertyInClass.kt, 12)
|
||||
field = propEx$delegate: delegatedPropertyInClass.MyDelegateThrowsException = {delegatedPropertyInClass.MyDelegateThrowsException@uniqueID} (sp = delegatedPropertyInClass.kt, 13)
|
||||
- No fields to display
|
||||
- Class has no fields
|
||||
field = propEx: int = {java.lang.IllegalStateException@uniqueID}java.lang.IllegalStateException (sp = delegatedPropertyInClass.kt, 13)
|
||||
field = detailMessage: java.lang.String = null (sp = Throwable.!EXT!)
|
||||
field = cause: java.lang.Throwable = {java.lang.IllegalStateException@uniqueID}java.lang.IllegalStateException (sp = Throwable.!EXT!)
|
||||
|
||||
@@ -26,7 +26,7 @@ class MyDelegate {
|
||||
local = args: java.lang.String[] = {java.lang.String[0]@uniqueID} (sp = delegatedPropertyInClassWoRenderer.kt, 5)
|
||||
local = a: delegatedPropertyInClassWoRenderer.A = {delegatedPropertyInClassWoRenderer.A@uniqueID} (sp = delegatedPropertyInClassWoRenderer.kt, 6)
|
||||
field = prop: int = {delegatedPropertyInClassWoRenderer.MyDelegate@uniqueID} (sp = delegatedPropertyInClassWoRenderer.kt, 12)
|
||||
- No fields to display
|
||||
- Class has no fields
|
||||
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||
|
||||
Process finished with exit code 0
|
||||
|
||||
+1
-1
@@ -38,7 +38,7 @@ class MyClass
|
||||
local = args: java.lang.String[] = {java.lang.String[0]@uniqueID} (sp = frameSimple.kt, 5)
|
||||
local = val1: int = 1 (sp = frameSimple.kt, 6)
|
||||
local = val2: frameSimple.MyClass = {frameSimple.MyClass@uniqueID} (sp = frameSimple.kt, 7)
|
||||
- No fields to display
|
||||
- Class has no fields
|
||||
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||
|
||||
Process finished with exit code 0
|
||||
|
||||
@@ -18,7 +18,7 @@ class A {
|
||||
frame = main():6, ToStringRendererKt {toStringRenderer}
|
||||
local = args: java.lang.String[] = {java.lang.String[0]@uniqueID} (sp = toStringRenderer.kt, 3)
|
||||
local = a: toStringRenderer.A = {toStringRenderer.A@uniqueID}myA (sp = toStringRenderer.kt, 4)
|
||||
- No fields to display
|
||||
- Class has no fields
|
||||
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||
|
||||
Process finished with exit code 0
|
||||
|
||||
@@ -468,8 +468,8 @@ public class KotlinJpsBuildTest : AbstractKotlinJpsBuildTestCase() {
|
||||
// Check that outputs are located properly
|
||||
val facadeWithA = findFileInOutputDir(findModule("module1"), "test/TestPackage.class")
|
||||
val facadeWithB = findFileInOutputDir(findModule("module2"), "test/TestPackage.class")
|
||||
UsefulTestCase.assertSameElements(getMethodsOfClass(facadeWithA), "<clinit>", "a", "getA")
|
||||
UsefulTestCase.assertSameElements(getMethodsOfClass(facadeWithB), "<clinit>", "b", "getB", "setB")
|
||||
UsefulTestCase.assertSameElements(getMethodsOfClass(facadeWithA), "a", "getA")
|
||||
UsefulTestCase.assertSameElements(getMethodsOfClass(facadeWithB), "b", "getB", "setB")
|
||||
|
||||
checkWhen(touch("module1/src/a.kt"), null, packageClasses("module1", "module1/src/a.kt", "test.TestPackage"))
|
||||
checkWhen(touch("module2/src/b.kt"), null, packageClasses("module2", "module2/src/b.kt", "test.TestPackage"))
|
||||
|
||||
Reference in New Issue
Block a user