Move and simplify AsmUtil.writeOuterClassAndEnclosingMethod

This commit is contained in:
Alexander Udalov
2015-02-05 23:08:33 +03:00
parent a280599969
commit 61a27da8d5
4 changed files with 49 additions and 68 deletions
@@ -27,7 +27,6 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.builtins.PrimitiveType;
import org.jetbrains.kotlin.codegen.binding.CalculatedClosure;
import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
import org.jetbrains.kotlin.codegen.context.CodegenContext;
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods;
import org.jetbrains.kotlin.codegen.state.GenerationState;
@@ -37,11 +36,7 @@ import org.jetbrains.kotlin.lexer.JetTokens;
import org.jetbrains.kotlin.load.java.JavaVisibilities;
import org.jetbrains.kotlin.load.java.JvmAbi;
import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor;
import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils;
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.psi.JetFile;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.resolve.annotations.AnnotationsPackage;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
@@ -62,7 +57,6 @@ import java.util.Map;
import java.util.Set;
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isInterface;
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.asmTypeForAnonymousClass;
import static org.jetbrains.kotlin.load.java.JvmAnnotationNames.ABI_VERSION_FIELD_NAME;
import static org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinSyntheticClass;
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
@@ -855,54 +849,6 @@ public class AsmUtil {
return JvmClassName.byFqNameWithoutInnerClasses(fqName).getInternalName();
}
public static void writeOuterClassAndEnclosingMethod(
@NotNull ClassDescriptor descriptor,
@NotNull DeclarationDescriptor originalDescriptor,
@NotNull JetTypeMapper typeMapper,
@NotNull ClassBuilder v
) {
String outerClassName = getOuterClassName(descriptor, originalDescriptor, typeMapper);
FunctionDescriptor function = DescriptorUtils.getParentOfType(descriptor, FunctionDescriptor.class);
while (function != null && JvmCodegenUtil.isLambdaWhichWillBeInlined(typeMapper.getBindingContext(), function)) {
function = DescriptorUtils.getParentOfType(function, FunctionDescriptor.class);
}
if (function != null) {
Method method = typeMapper.mapSignature(function).getAsmMethod();
v.visitOuterClass(outerClassName, method.getName(), method.getDescriptor());
}
else {
v.visitOuterClass(outerClassName, null, null);
}
}
@NotNull
private static String getOuterClassName(
@NotNull ClassDescriptor classDescriptor,
@NotNull DeclarationDescriptor originalDescriptor,
@NotNull JetTypeMapper typeMapper
) {
BindingContext bindingContext = typeMapper.getBindingContext();
DeclarationDescriptor container = classDescriptor.getContainingDeclaration();
while (container != null) {
if (container instanceof ClassDescriptor) {
return typeMapper.mapClass((ClassDescriptor) container).getInternalName();
}
else if (CodegenBinding.isLocalFunOrLambda(container) &&
!JvmCodegenUtil.isLambdaWhichWillBeInlined(bindingContext, container)) {
return asmTypeForAnonymousClass(bindingContext, (FunctionDescriptor) container).getInternalName();
}
container = container.getContainingDeclaration();
}
JetFile containingFile = DescriptorToSourceUtils.getContainingFile(originalDescriptor);
assert containingFile != null : "Containing file should be present for " + classDescriptor;
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;");
@@ -209,7 +209,7 @@ public class ClosureCodegen extends MemberCodegen<JetElement> {
@Override
protected void done() {
writeOuterClassAndEnclosingMethod(classDescriptor, funDescriptor, typeMapper, v);
writeOuterClassAndEnclosingMethod(classDescriptor);
super.done();
}
@@ -249,16 +249,14 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
private void writeEnclosingMethod() {
//JVMS7: A class must have an EnclosingMethod attribute if and only if it is a local class or an anonymous class.
DeclarationDescriptor parentDescriptor = descriptor.getContainingDeclaration();
boolean isObjectLiteral = DescriptorUtils.isAnonymousObject(descriptor);
boolean isLocalOrAnonymousClass = isObjectLiteral ||
!(parentDescriptor instanceof PackageFragmentDescriptor || parentDescriptor instanceof ClassDescriptor);
// Do not emit enclosing method in "light-classes mode" since currently we generate local light classes as if they're top level
if (isLocalOrAnonymousClass && state.getClassBuilderMode() != ClassBuilderMode.LIGHT_CLASSES) {
writeOuterClassAndEnclosingMethod(descriptor, descriptor, typeMapper, v);
if (state.getClassBuilderMode() == ClassBuilderMode.LIGHT_CLASSES) {
return;
}
//JVMS7: A class must have an EnclosingMethod attribute if and only if it is a local class or an anonymous class.
if (isAnonymousObject(descriptor) || !(descriptor.getContainingDeclaration() instanceof ClassOrPackageFragmentDescriptor)) {
writeOuterClassAndEnclosingMethod(descriptor);
}
}
@@ -20,6 +20,7 @@ import com.intellij.openapi.progress.ProcessCanceledException;
import kotlin.Function0;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
import org.jetbrains.kotlin.codegen.context.ClassContext;
import org.jetbrains.kotlin.codegen.context.CodegenContext;
import org.jetbrains.kotlin.codegen.context.FieldOwnerContext;
@@ -32,13 +33,11 @@ import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl;
import org.jetbrains.kotlin.load.java.JvmAbi;
import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.name.SpecialNames;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.BindingContextUtils;
import org.jetbrains.kotlin.resolve.BindingTrace;
import org.jetbrains.kotlin.resolve.TemporaryBindingTrace;
import org.jetbrains.kotlin.resolve.*;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant;
import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstant;
@@ -250,6 +249,44 @@ public abstract class MemberCodegen<T extends JetElement/* TODO: & JetDeclaratio
v.visitInnerClass(innerClassInternalName, outerClassInternalName, innerName, calculateInnerClassAccessFlags(innerClass));
}
protected void writeOuterClassAndEnclosingMethod(@NotNull ClassDescriptor descriptor) {
ClassDescriptor outerClass = findOuterClass(descriptor);
String outerClassName = outerClass != null
? typeMapper.mapClass(outerClass).getInternalName()
: PackagePartClassUtils.getPackagePartInternalName(element.getContainingJetFile());
FunctionDescriptor function = DescriptorUtils.getParentOfType(descriptor, FunctionDescriptor.class);
while (function != null && JvmCodegenUtil.isLambdaWhichWillBeInlined(bindingContext, function)) {
function = DescriptorUtils.getParentOfType(function, FunctionDescriptor.class);
}
if (function != null) {
Method method = typeMapper.mapSignature(function).getAsmMethod();
v.visitOuterClass(outerClassName, method.getName(), method.getDescriptor());
}
else {
v.visitOuterClass(outerClassName, null, null);
}
}
@Nullable
private ClassDescriptor findOuterClass(@NotNull ClassDescriptor classDescriptor) {
DeclarationDescriptor container = classDescriptor.getContainingDeclaration();
while (container != null) {
if (container instanceof ClassDescriptor) {
return (ClassDescriptor) container;
}
else if (CodegenBinding.isLocalFunOrLambda(container) &&
!JvmCodegenUtil.isLambdaWhichWillBeInlined(bindingContext, container)) {
return CodegenBinding.anonymousClassForFunction(bindingContext, (FunctionDescriptor) container);
}
container = container.getContainingDeclaration();
}
return null;
}
@NotNull
public NameGenerator getInlineNameGenerator() {
if (inlineNameGenerator == null) {