Drop erased class for inline class
This commit is contained in:
@@ -5,7 +5,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen
|
||||
|
||||
import com.intellij.util.ArrayUtil
|
||||
import org.jetbrains.kotlin.codegen.context.ClassContext
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
||||
@@ -15,13 +14,9 @@ import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||
import org.jetbrains.kotlin.resolve.InlineClassDescriptorResolver
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.secondaryConstructors
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErasedInlineClassOrigin
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.Synthetic
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
|
||||
class ErasedInlineClassBodyCodegen(
|
||||
aClass: KtClass,
|
||||
@@ -31,25 +26,19 @@ class ErasedInlineClassBodyCodegen(
|
||||
parentCodegen: MemberCodegen<*>?
|
||||
) : ClassBodyCodegen(aClass, context, v, state, parentCodegen) {
|
||||
|
||||
private val classAsmType = typeMapper.mapErasedInlineClass(descriptor)
|
||||
private val classAsmType = typeMapper.mapClass(descriptor)
|
||||
|
||||
private val constructorCodegen = ConstructorCodegen(
|
||||
descriptor, context, functionCodegen, this, this, state, kind, v, classAsmType, aClass, bindingContext
|
||||
)
|
||||
|
||||
override fun generateDeclaration() {
|
||||
v.defineClass(
|
||||
myClass.psiOrParent, state.classFileVersion, Opcodes.ACC_STATIC,
|
||||
classAsmType.internalName, null, "java/lang/Object", ArrayUtil.EMPTY_STRING_ARRAY
|
||||
)
|
||||
v.visitSource(myClass.containingKtFile.name, null)
|
||||
}
|
||||
override fun generateDeclaration() {}
|
||||
override fun generateKotlinMetadataAnnotation() {}
|
||||
override fun done() {}
|
||||
|
||||
override fun generateConstructors() {
|
||||
val delegationFieldsInfo = DelegationFieldsInfo(classAsmType, descriptor, state, bindingContext)
|
||||
|
||||
generateDefaultConstructorForErasedInlineClass()
|
||||
|
||||
constructorCodegen.generatePrimaryConstructor(delegationFieldsInfo, AsmTypes.OBJECT_TYPE)
|
||||
|
||||
for (secondaryConstructor in descriptor.secondaryConstructors) {
|
||||
@@ -57,21 +46,6 @@ class ErasedInlineClassBodyCodegen(
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateDefaultConstructorForErasedInlineClass() {
|
||||
val mv = v.newMethod(
|
||||
ErasedInlineClassOrigin(myClass.psiOrParent, descriptor), 0,
|
||||
"<init>", "()V", null, ArrayUtil.EMPTY_STRING_ARRAY
|
||||
)
|
||||
mv.visitCode()
|
||||
InstructionAdapter(mv).apply {
|
||||
load(0, AsmTypes.OBJECT_TYPE)
|
||||
invokespecial(AsmTypes.OBJECT_TYPE.internalName, "<init>", "()V", false)
|
||||
areturn(Type.VOID_TYPE)
|
||||
}
|
||||
mv.visitMaxs(1, 1)
|
||||
mv.visitEnd()
|
||||
}
|
||||
|
||||
override fun generateSyntheticPartsAfterBody() {
|
||||
super.generateSyntheticPartsAfterBody()
|
||||
|
||||
@@ -141,8 +115,4 @@ class ErasedInlineClassBodyCodegen(
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
override fun generateKotlinMetadataAnnotation() {
|
||||
writeSyntheticClassMetadata(v, state)
|
||||
}
|
||||
}
|
||||
@@ -225,7 +225,7 @@ public class FunctionCodegen {
|
||||
asmMethod.getDescriptor()
|
||||
);
|
||||
|
||||
if (CodegenContextUtil.isImplClassOwner(owner)) {
|
||||
if (CodegenContextUtil.isImplementationOwner(owner, functionDescriptor)) {
|
||||
v.getSerializationBindings().put(METHOD_FOR_FUNCTION, CodegenUtilKt.unwrapFrontendVersion(functionDescriptor), asmMethod);
|
||||
}
|
||||
|
||||
@@ -307,7 +307,7 @@ public class FunctionCodegen {
|
||||
}
|
||||
|
||||
// base check
|
||||
boolean isInlineClass = isClass(containingDeclaration) && ((ClassDescriptor) containingDeclaration).isInline();
|
||||
boolean isInlineClass = InlineClassesUtilsKt.isInlineClass(containingDeclaration);
|
||||
boolean simpleFunctionOrProperty =
|
||||
!(functionDescriptor instanceof ConstructorDescriptor) && !KotlinTypeMapper.isAccessor(functionDescriptor);
|
||||
|
||||
@@ -323,10 +323,8 @@ public class FunctionCodegen {
|
||||
) {
|
||||
mv.visitCode();
|
||||
|
||||
Type inlineErasedType = typeMapper.mapErasedInlineClass(containingDeclaration);
|
||||
Method erasedMethodImpl = typeMapper.mapAsmMethod(functionDescriptor.getOriginal(), OwnerKind.ERASED_INLINE_CLASS);
|
||||
|
||||
Type fieldOwnerType = typeMapper.mapClass(containingDeclaration);
|
||||
Method erasedMethodImpl = typeMapper.mapAsmMethod(functionDescriptor.getOriginal(), OwnerKind.ERASED_INLINE_CLASS);
|
||||
|
||||
ValueParameterDescriptor valueRepresentation = InlineClassesUtilsKt.underlyingRepresentation(containingDeclaration);
|
||||
if (valueRepresentation == null) return;
|
||||
@@ -334,7 +332,7 @@ public class FunctionCodegen {
|
||||
Type fieldType = typeMapper.mapType(valueRepresentation);
|
||||
|
||||
generateDelegateToStaticErasedVersion(
|
||||
mv, erasedMethodImpl, inlineErasedType.getInternalName(),
|
||||
mv, erasedMethodImpl,
|
||||
fieldOwnerType, valueRepresentation.getName().asString(), fieldType
|
||||
);
|
||||
|
||||
@@ -915,11 +913,11 @@ public class FunctionCodegen {
|
||||
private static void generateDelegateToStaticErasedVersion(
|
||||
@NotNull MethodVisitor mv,
|
||||
@NotNull Method erasedStaticAsmMethod,
|
||||
@NotNull String classToDelegateTo,
|
||||
@NotNull Type fieldOwnerType,
|
||||
@NotNull String fieldName,
|
||||
@NotNull Type fieldType
|
||||
) {
|
||||
String internalName = fieldOwnerType.getInternalName();
|
||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
Type[] argTypes = erasedStaticAsmMethod.getArgumentTypes();
|
||||
|
||||
@@ -928,7 +926,7 @@ public class FunctionCodegen {
|
||||
iv.visitLineNumber(1, label);
|
||||
|
||||
iv.load(0, AsmTypes.OBJECT_TYPE);
|
||||
iv.visitFieldInsn(Opcodes.GETFIELD, fieldOwnerType.getInternalName(), fieldName, fieldType.getDescriptor());
|
||||
iv.visitFieldInsn(Opcodes.GETFIELD, internalName, fieldName, fieldType.getDescriptor());
|
||||
|
||||
int k = 1;
|
||||
for (int i = 1; i < argTypes.length; i++) {
|
||||
@@ -937,7 +935,7 @@ public class FunctionCodegen {
|
||||
k += argType.getSize();
|
||||
}
|
||||
|
||||
iv.invokestatic(classToDelegateTo, erasedStaticAsmMethod.getName(), erasedStaticAsmMethod.getDescriptor(), false);
|
||||
iv.invokestatic(internalName, erasedStaticAsmMethod.getName(), erasedStaticAsmMethod.getDescriptor(), false);
|
||||
iv.areturn(erasedStaticAsmMethod.getReturnType());
|
||||
}
|
||||
|
||||
|
||||
@@ -256,18 +256,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
if (!(myClass instanceof KtClass)) return;
|
||||
if (!descriptor.isInline()) return;
|
||||
|
||||
Type erasedInlineClassType = state.getTypeMapper().mapErasedInlineClass(descriptor);
|
||||
ClassBuilder builder = state.getFactory().newVisitor(
|
||||
JvmDeclarationOriginKt.ErasedInlineClassOrigin(myClass.getPsiOrParent(), descriptor),
|
||||
erasedInlineClassType,
|
||||
myClass.getContainingKtFile()
|
||||
);
|
||||
|
||||
CodegenContext parentContext = context.getParentContext();
|
||||
assert parentContext != null : "Parent context of inline class declaration should not be null";
|
||||
|
||||
ClassContext erasedInlineClassContext = parentContext.intoWrapperForErasedInlineClass(descriptor, state);
|
||||
new ErasedInlineClassBodyCodegen((KtClass) myClass, erasedInlineClassContext, builder, state, this).generate();
|
||||
new ErasedInlineClassBodyCodegen((KtClass) myClass, erasedInlineClassContext, v, state, this).generate();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -243,7 +243,7 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
||||
}
|
||||
|
||||
private void genTypeAliasAnnotationsMethodIfRequired(TypeAliasDescriptor typeAliasDescriptor) {
|
||||
boolean isAnnotationsMethodOwner = CodegenContextUtil.isImplClassOwner(context);
|
||||
boolean isAnnotationsMethodOwner = CodegenContextUtil.isImplementationOwner(context, typeAliasDescriptor);
|
||||
Annotations annotations = typeAliasDescriptor.getAnnotations();
|
||||
if (!isAnnotationsMethodOwner || annotations.isEmpty()) return;
|
||||
|
||||
|
||||
@@ -159,7 +159,7 @@ public class PropertyCodegen {
|
||||
// Fields and '$annotations' methods for non-private const properties are generated in the multi-file facade
|
||||
boolean isBackingFieldOwner = descriptor.isConst() && !Visibilities.isPrivate(descriptor.getVisibility())
|
||||
? !(context instanceof MultifileClassPartContext)
|
||||
: CodegenContextUtil.isImplClassOwner(context);
|
||||
: CodegenContextUtil.isImplementationOwner(context, descriptor);
|
||||
|
||||
assert declaration != null : "Declaration is null: " + descriptor + " (context=" + context + ")";
|
||||
generateBackingField(declaration, descriptor, isBackingFieldOwner);
|
||||
@@ -338,7 +338,7 @@ public class PropertyCodegen {
|
||||
if (annotations.isEmpty()) return;
|
||||
|
||||
Method signature = getSyntheticMethodSignature(descriptor);
|
||||
if (kind != OwnerKind.DEFAULT_IMPLS && CodegenContextUtil.isImplClassOwner(context)) {
|
||||
if (kind != OwnerKind.DEFAULT_IMPLS && CodegenContextUtil.isImplementationOwner(context, descriptor)) {
|
||||
v.getSerializationBindings().put(SYNTHETIC_METHOD_FOR_PROPERTY, descriptor, signature);
|
||||
}
|
||||
|
||||
|
||||
@@ -37,10 +37,6 @@ class SuperClassInfo(
|
||||
return SuperClassInfo(OBJECT_TYPE, null)
|
||||
}
|
||||
|
||||
if (descriptor.isInline) {
|
||||
return SuperClassInfo(typeMapper.mapErasedInlineClass(descriptor), null)
|
||||
}
|
||||
|
||||
for (supertype in descriptor.typeConstructor.supertypes) {
|
||||
val superClass = supertype.constructor.declarationDescriptor
|
||||
if (superClass != null && !isJvmInterface(superClass)) {
|
||||
|
||||
@@ -16,16 +16,31 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen.context
|
||||
|
||||
import org.jetbrains.kotlin.codegen.OwnerKind
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.resolve.isInlineClass
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
|
||||
object CodegenContextUtil {
|
||||
@JvmStatic fun getImplementationOwnerClassType(owner: CodegenContext<*>): Type? =
|
||||
when (owner) {
|
||||
is MultifileClassFacadeContext -> owner.filePartType
|
||||
is DelegatingToPartContext -> owner.implementationOwnerClassType
|
||||
else -> null
|
||||
}
|
||||
@JvmStatic
|
||||
fun getImplementationOwnerClassType(owner: CodegenContext<*>): Type? =
|
||||
when (owner) {
|
||||
is MultifileClassFacadeContext -> owner.filePartType
|
||||
is DelegatingToPartContext -> owner.implementationOwnerClassType
|
||||
else -> null
|
||||
}
|
||||
|
||||
@JvmStatic fun isImplClassOwner(owner: CodegenContext<*>): Boolean =
|
||||
owner !is MultifileClassFacadeContext
|
||||
@JvmStatic
|
||||
fun isImplementationOwner(owner: CodegenContext<*>, descriptor: DeclarationDescriptor): Boolean {
|
||||
if (descriptor.containingDeclaration?.isInlineClass() == true) {
|
||||
val isInErasedMethod = owner.contextKind == OwnerKind.ERASED_INLINE_CLASS
|
||||
when (descriptor) {
|
||||
is FunctionDescriptor -> return isInErasedMethod
|
||||
is PropertyDescriptor -> return !isInErasedMethod
|
||||
}
|
||||
}
|
||||
return owner !is MultifileClassFacadeContext
|
||||
}
|
||||
}
|
||||
|
||||
@@ -327,9 +327,6 @@ public class KotlinTypeMapper {
|
||||
if (isInterface(classDescriptor)) {
|
||||
nestedClass = JvmAbi.DEFAULT_IMPLS_SUFFIX;
|
||||
}
|
||||
else if (classDescriptor.isInline()) {
|
||||
nestedClass = JvmAbi.ERASED_INLINE_CLASS_SUFFIX;
|
||||
}
|
||||
else {
|
||||
nestedClass = null;
|
||||
}
|
||||
@@ -479,10 +476,6 @@ public class KotlinTypeMapper {
|
||||
return mapTypeAsDeclaration(descriptor.getReturnType());
|
||||
}
|
||||
|
||||
public Type mapErasedInlineClass(@NotNull ClassDescriptor descriptor) {
|
||||
return Type.getObjectType(mapClass(descriptor).getInternalName() + JvmAbi.ERASED_INLINE_CLASS_SUFFIX);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JvmMethodGenericSignature mapAnnotationParameterSignature(@NotNull PropertyDescriptor descriptor) {
|
||||
JvmSignatureWriter sw = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD);
|
||||
@@ -533,13 +526,6 @@ public class KotlinTypeMapper {
|
||||
return mapInlineClassType(underlyingType, TypeMappingMode.DEFAULT);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Type mapToErasedInlineClassType(@NotNull KotlinType kotlinType) {
|
||||
return Type.getObjectType(
|
||||
mapInlineClassTypeAsDeclaration(kotlinType).getInternalName() + JvmAbi.ERASED_INLINE_CLASS_SUFFIX
|
||||
);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Type mapInlineClassType(@NotNull KotlinType kotlinType) {
|
||||
return mapInlineClassType(kotlinType, TypeMappingMode.DEFAULT);
|
||||
|
||||
Reference in New Issue
Block a user