Simplify clinit codegen, delete code duplication

Logic for <clinit> generation was present both in PackagePartCodegen and in
ClassBodyCodegen, move it to MemberCodegen
This commit is contained in:
Alexander Udalov
2014-04-21 19:23:36 +04:00
parent be47897e18
commit 6803fec053
4 changed files with 79 additions and 130 deletions
@@ -21,32 +21,24 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.codegen.bridges.BridgesPackage; import org.jetbrains.jet.codegen.bridges.BridgesPackage;
import org.jetbrains.jet.codegen.context.ClassContext; import org.jetbrains.jet.codegen.context.ClassContext;
import org.jetbrains.jet.codegen.state.GenerationState; import org.jetbrains.jet.codegen.state.GenerationState;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.annotations.Annotations; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.impl.SimpleFunctionDescriptorImpl; import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.org.objectweb.asm.MethodVisitor;
import org.jetbrains.org.objectweb.asm.Type;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.enumEntryNeedSubclass; import static org.jetbrains.jet.codegen.binding.CodegenBinding.enumEntryNeedSubclass;
import static org.jetbrains.org.objectweb.asm.Opcodes.ACC_STATIC;
import static org.jetbrains.org.objectweb.asm.Opcodes.RETURN; import static org.jetbrains.org.objectweb.asm.Opcodes.RETURN;
public abstract class ClassBodyCodegen extends MemberCodegen { public abstract class ClassBodyCodegen extends MemberCodegen {
protected final JetClassOrObject myClass; protected final JetClassOrObject myClass;
protected final OwnerKind kind; protected final OwnerKind kind;
protected final ClassDescriptor descriptor; protected final ClassDescriptor descriptor;
protected final ClassBuilder v;
private MethodVisitor clInitMethod;
private ExpressionCodegen clInitCodegen;
protected ClassBodyCodegen( protected ClassBodyCodegen(
@NotNull JetClassOrObject aClass, @NotNull JetClassOrObject aClass,
@@ -56,10 +48,9 @@ public abstract class ClassBodyCodegen extends MemberCodegen {
@Nullable MemberCodegen parentCodegen @Nullable MemberCodegen parentCodegen
) { ) {
super(state, parentCodegen, context, v); super(state, parentCodegen, context, v);
descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
myClass = aClass; myClass = aClass;
this.kind = context.getContextKind(); kind = context.getContextKind();
this.v = v; descriptor = bindingContext.get(BindingContext.CLASS, aClass);
} }
public void generate() { public void generate() {
@@ -69,7 +60,7 @@ public abstract class ClassBodyCodegen extends MemberCodegen {
generateSyntheticParts(); generateSyntheticParts();
generateStaticInitializer(); completeStaticInitializer();
generateKotlinAnnotation(); generateKotlinAnnotation();
} }
@@ -152,49 +143,18 @@ public abstract class ClassBodyCodegen extends MemberCodegen {
} }
} }
protected @NotNull List<JetParameter> getPrimaryConstructorParameters() { @NotNull
protected List<JetParameter> getPrimaryConstructorParameters() {
if (myClass instanceof JetClass) { if (myClass instanceof JetClass) {
return ((JetClass) myClass).getPrimaryConstructorParameters(); return ((JetClass) myClass).getPrimaryConstructorParameters();
} }
return Collections.emptyList(); return Collections.emptyList();
} }
private void generateStaticInitializer() { private void completeStaticInitializer() {
if (clInitMethod != null) { if (clInit != null) {
createOrGetClInitMethod(); clInit.v.visitInsn(RETURN);
FunctionCodegen.endVisit(clInit.v, "static initializer", myClass);
if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
ExpressionCodegen codegen = createOrGetClInitCodegen();
createOrGetClInitMethod().visitInsn(RETURN);
FunctionCodegen.endVisit(codegen.v, "static initializer", myClass);
}
} }
} }
@NotNull
protected MethodVisitor createOrGetClInitMethod() {
if (clInitMethod == null) {
clInitMethod = v.newMethod(null, ACC_STATIC, "<clinit>", "()V", null, null);
}
return clInitMethod;
}
@NotNull
protected ExpressionCodegen createOrGetClInitCodegen() {
assert state.getClassBuilderMode() == ClassBuilderMode.FULL;
if (clInitCodegen == null) {
MethodVisitor method = createOrGetClInitMethod();
method.visitCode();
SimpleFunctionDescriptorImpl clInit =
SimpleFunctionDescriptorImpl.create(descriptor, Annotations.EMPTY,
Name.special("<clinit>"),
CallableMemberDescriptor.Kind.SYNTHESIZED);
clInit.initialize(null, null, Collections.<TypeParameterDescriptor>emptyList(),
Collections.<ValueParameterDescriptor>emptyList(), null, null, Visibilities.PRIVATE);
clInitCodegen = new ExpressionCodegen(method, new FrameMap(), Type.VOID_TYPE, context.intoFunction(clInit), state, this);
}
return clInitCodegen;
}
} }
@@ -19,24 +19,32 @@ package org.jetbrains.jet.codegen;
import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProcessCanceledException;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.codegen.inline.InlineCodegenUtil;
import org.jetbrains.jet.codegen.inline.NameGenerator;
import org.jetbrains.jet.codegen.context.ClassContext; import org.jetbrains.jet.codegen.context.ClassContext;
import org.jetbrains.jet.codegen.context.CodegenContext; import org.jetbrains.jet.codegen.context.CodegenContext;
import org.jetbrains.jet.codegen.context.FieldOwnerContext; import org.jetbrains.jet.codegen.context.FieldOwnerContext;
import org.jetbrains.jet.codegen.inline.InlineCodegenUtil;
import org.jetbrains.jet.codegen.inline.NameGenerator;
import org.jetbrains.jet.codegen.state.GenerationState; import org.jetbrains.jet.codegen.state.GenerationState;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.Annotations;
import org.jetbrains.jet.lang.descriptors.impl.SimpleFunctionDescriptorImpl;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.name.SpecialNames; import org.jetbrains.jet.lang.resolve.name.SpecialNames;
import org.jetbrains.jet.lang.types.ErrorUtils; import org.jetbrains.jet.lang.types.ErrorUtils;
import org.jetbrains.org.objectweb.asm.MethodVisitor;
import org.jetbrains.org.objectweb.asm.Type;
import java.util.Collections;
import static org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor.Kind.SYNTHESIZED;
import static org.jetbrains.org.objectweb.asm.Opcodes.ACC_STATIC;
public class MemberCodegen extends ParentCodegenAwareImpl { public class MemberCodegen extends ParentCodegenAwareImpl {
protected final FieldOwnerContext context; protected final FieldOwnerContext context;
protected final ClassBuilder v;
private final ClassBuilder builder; protected ExpressionCodegen clInit;
private NameGenerator inlineNameGenerator; private NameGenerator inlineNameGenerator;
@@ -44,11 +52,11 @@ public class MemberCodegen extends ParentCodegenAwareImpl {
@NotNull GenerationState state, @NotNull GenerationState state,
@Nullable MemberCodegen parentCodegen, @Nullable MemberCodegen parentCodegen,
@NotNull FieldOwnerContext context, @NotNull FieldOwnerContext context,
@Nullable ClassBuilder builder ClassBuilder builder
) { ) {
super(state, parentCodegen); super(state, parentCodegen);
this.context = context; this.context = context;
this.builder = builder; this.v = builder;
} }
public void genFunctionOrProperty( public void genFunctionOrProperty(
@@ -121,8 +129,7 @@ public class MemberCodegen extends ParentCodegenAwareImpl {
private static void badDescriptor(ClassDescriptor descriptor, ClassBuilderMode mode) { private static void badDescriptor(ClassDescriptor descriptor, ClassBuilderMode mode) {
if (mode != ClassBuilderMode.LIGHT_CLASSES) { if (mode != ClassBuilderMode.LIGHT_CLASSES) {
throw new IllegalStateException( throw new IllegalStateException("Generating bad descriptor in ClassBuilderMode = " + mode + ": " + descriptor);
"Generating bad descriptor in ClassBuilderMode = " + mode + ": " + descriptor);
} }
} }
@@ -132,15 +139,33 @@ public class MemberCodegen extends ParentCodegenAwareImpl {
@NotNull @NotNull
public ClassBuilder getBuilder() { public ClassBuilder getBuilder() {
return builder; return v;
} }
@NotNull
public NameGenerator getInlineNameGenerator() { public NameGenerator getInlineNameGenerator() {
if (inlineNameGenerator == null) { if (inlineNameGenerator == null) {
String prefix = InlineCodegenUtil.getInlineName(context, typeMapper); String prefix = InlineCodegenUtil.getInlineName(context, typeMapper);
inlineNameGenerator = new NameGenerator(prefix); inlineNameGenerator = new NameGenerator(prefix);
} }
return inlineNameGenerator; return inlineNameGenerator;
} }
@NotNull
protected ExpressionCodegen createOrGetClInitCodegen() {
DeclarationDescriptor descriptor = context.getContextDescriptor();
assert state.getClassBuilderMode() == ClassBuilderMode.FULL
: "<clinit> should not be generated for light classes. Descriptor: " + descriptor;
if (clInit == null) {
MethodVisitor mv = v.newMethod(null, ACC_STATIC, "<clinit>", "()V", null, null);
mv.visitCode();
SimpleFunctionDescriptorImpl clInit =
SimpleFunctionDescriptorImpl.create(descriptor, Annotations.EMPTY, Name.special("<clinit>"), SYNTHESIZED);
clInit.initialize(null, null, Collections.<TypeParameterDescriptor>emptyList(),
Collections.<ValueParameterDescriptor>emptyList(), null, null, Visibilities.PRIVATE);
this.clInit = new ExpressionCodegen(mv, new FrameMap(), Type.VOID_TYPE, context.intoFunction(clInit), state, this);
}
return clInit;
}
} }
@@ -28,9 +28,6 @@ import com.intellij.util.PathUtil;
import com.intellij.util.SmartList; import com.intellij.util.SmartList;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.org.objectweb.asm.AnnotationVisitor;
import org.jetbrains.org.objectweb.asm.MethodVisitor;
import org.jetbrains.org.objectweb.asm.Type;
import org.jetbrains.jet.codegen.context.CodegenContext; import org.jetbrains.jet.codegen.context.CodegenContext;
import org.jetbrains.jet.codegen.context.FieldOwnerContext; import org.jetbrains.jet.codegen.context.FieldOwnerContext;
import org.jetbrains.jet.codegen.context.MethodContext; import org.jetbrains.jet.codegen.context.MethodContext;
@@ -39,7 +36,10 @@ import org.jetbrains.jet.codegen.signature.JvmMethodSignature;
import org.jetbrains.jet.codegen.state.GenerationState; import org.jetbrains.jet.codegen.state.GenerationState;
import org.jetbrains.jet.codegen.state.GenerationStateAware; import org.jetbrains.jet.codegen.state.GenerationStateAware;
import org.jetbrains.jet.config.IncrementalCompilation; import org.jetbrains.jet.config.IncrementalCompilation;
import org.jetbrains.jet.descriptors.serialization.*; import org.jetbrains.jet.descriptors.serialization.BitEncoding;
import org.jetbrains.jet.descriptors.serialization.DescriptorSerializer;
import org.jetbrains.jet.descriptors.serialization.PackageData;
import org.jetbrains.jet.descriptors.serialization.ProtoBuf;
import org.jetbrains.jet.descriptors.serialization.descriptors.DeserializedCallableMemberDescriptor; import org.jetbrains.jet.descriptors.serialization.descriptors.DeserializedCallableMemberDescriptor;
import org.jetbrains.jet.descriptors.serialization.descriptors.DeserializedPropertyDescriptor; import org.jetbrains.jet.descriptors.serialization.descriptors.DeserializedPropertyDescriptor;
import org.jetbrains.jet.descriptors.serialization.descriptors.DeserializedSimpleFunctionDescriptor; import org.jetbrains.jet.descriptors.serialization.descriptors.DeserializedSimpleFunctionDescriptor;
@@ -57,14 +57,17 @@ import org.jetbrains.jet.lang.resolve.java.lazy.descriptors.LazyJavaPackageFragm
import org.jetbrains.jet.lang.resolve.kotlin.BaseDescriptorDeserializer; import org.jetbrains.jet.lang.resolve.kotlin.BaseDescriptorDeserializer;
import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.org.objectweb.asm.AnnotationVisitor;
import org.jetbrains.org.objectweb.asm.MethodVisitor;
import org.jetbrains.org.objectweb.asm.Type;
import java.util.*; import java.util.*;
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
import static org.jetbrains.jet.codegen.AsmUtil.asmDescByFqNameWithoutInnerClasses; import static org.jetbrains.jet.codegen.AsmUtil.asmDescByFqNameWithoutInnerClasses;
import static org.jetbrains.jet.codegen.AsmUtil.asmTypeByFqNameWithoutInnerClasses; import static org.jetbrains.jet.codegen.AsmUtil.asmTypeByFqNameWithoutInnerClasses;
import static org.jetbrains.jet.descriptors.serialization.NameSerializationUtil.createNameResolver; import static org.jetbrains.jet.descriptors.serialization.NameSerializationUtil.createNameResolver;
import static org.jetbrains.jet.lang.resolve.java.PackageClassUtils.getPackageClassFqName; import static org.jetbrains.jet.lang.resolve.java.PackageClassUtils.getPackageClassFqName;
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
public class PackageCodegen extends GenerationStateAware { public class PackageCodegen extends GenerationStateAware {
@NotNull @NotNull
@@ -321,7 +324,7 @@ public class PackageCodegen extends GenerationStateAware {
@NotNull @NotNull
@Override @Override
public ClassBuilder getBuilder() { public ClassBuilder getBuilder() {
return v.getClassBuilder(); return PackageCodegen.this.v.getClassBuilder();
} }
}; };
} }
@@ -19,56 +19,37 @@ package org.jetbrains.jet.codegen;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.intellij.util.ArrayUtil; import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.org.objectweb.asm.MethodVisitor;
import org.jetbrains.org.objectweb.asm.Type;
import org.jetbrains.jet.codegen.context.FieldOwnerContext; import org.jetbrains.jet.codegen.context.FieldOwnerContext;
import org.jetbrains.jet.codegen.state.GenerationState; import org.jetbrains.jet.codegen.state.GenerationState;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.Annotations;
import org.jetbrains.jet.lang.descriptors.impl.SimpleFunctionDescriptorImpl;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.org.objectweb.asm.Type;
import org.jetbrains.jet.lang.resolve.name.Name;
import java.util.Collections;
import java.util.List; import java.util.List;
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
import static org.jetbrains.jet.codegen.AsmUtil.writeKotlinSyntheticClassAnnotation; import static org.jetbrains.jet.codegen.AsmUtil.writeKotlinSyntheticClassAnnotation;
import static org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames.KotlinSyntheticClass; import static org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames.KotlinSyntheticClass;
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
public class PackagePartCodegen extends MemberCodegen { public class PackagePartCodegen extends MemberCodegen {
private final ClassBuilder v;
private final PackageFragmentDescriptor descriptor;
private final JetFile jetFile; private final JetFile jetFile;
private final Type packagePartType;
private final Type packagePartName;
private final FieldOwnerContext context;
public PackagePartCodegen( public PackagePartCodegen(
@NotNull ClassBuilder v, @NotNull ClassBuilder v,
@NotNull JetFile jetFile, @NotNull JetFile jetFile,
@NotNull Type packagePartName, @NotNull Type packagePartType,
@NotNull FieldOwnerContext context, @NotNull FieldOwnerContext context,
@NotNull GenerationState state @NotNull GenerationState state
) { ) {
super(state, null, context, v); super(state, null, context, v);
this.v = v;
this.jetFile = jetFile; this.jetFile = jetFile;
this.packagePartName = packagePartName; this.packagePartType = packagePartType;
this.context = context;
descriptor = state.getBindingContext().get(BindingContext.FILE_TO_PACKAGE_FRAGMENT, jetFile);
assert descriptor != null : "No package fragment found for jetFile " + jetFile + " declared package: " + jetFile.getPackageFqName();
} }
public void generate() { public void generate() {
v.defineClass(jetFile, V1_6, v.defineClass(jetFile, V1_6,
ACC_PUBLIC | ACC_FINAL, ACC_PUBLIC | ACC_FINAL,
packagePartName.getInternalName(), packagePartType.getInternalName(),
null, null,
"java/lang/Object", "java/lang/Object",
ArrayUtil.EMPTY_STRING_ARRAY ArrayUtil.EMPTY_STRING_ARRAY
@@ -89,44 +70,24 @@ public class PackagePartCodegen extends MemberCodegen {
} }
private void generateStaticInitializers() { private void generateStaticInitializers() {
List<JetProperty> properties = collectPropertiesToInitialize(); List<JetProperty> properties = Lists.newArrayList();
for (JetDeclaration declaration : jetFile.getDeclarations()) {
if (declaration instanceof JetProperty) {
JetProperty property = (JetProperty) declaration;
if (ImplementationBodyCodegen.shouldInitializeProperty(property, typeMapper)) {
properties.add(property);
}
}
}
if (properties.isEmpty()) return; if (properties.isEmpty()) return;
MethodVisitor mv = v.newMethod(jetFile, ACC_STATIC, "<clinit>", "()V", null, null); ExpressionCodegen codegen = createOrGetClInitCodegen();
if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode();
FrameMap frameMap = new FrameMap(); for (JetProperty property : properties) {
ImplementationBodyCodegen.initializeProperty(codegen, bindingContext, property);
SimpleFunctionDescriptorImpl clInit =
SimpleFunctionDescriptorImpl.create(this.descriptor, Annotations.EMPTY,
Name.special("<clinit>"),
CallableMemberDescriptor.Kind.SYNTHESIZED);
clInit.initialize(null, null, Collections.<TypeParameterDescriptor>emptyList(),
Collections.<ValueParameterDescriptor>emptyList(), null, null, Visibilities.PRIVATE);
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, this.context.intoFunction(clInit), state, this);
for (JetDeclaration declaration : properties) {
ImplementationBodyCodegen.
initializeProperty(codegen, state.getBindingContext(), (JetProperty) declaration);
}
mv.visitInsn(RETURN);
FunctionCodegen.endVisit(mv, "static initializer for package", jetFile);
mv.visitEnd();
} }
}
@NotNull codegen.v.visitInsn(RETURN);
private List<JetProperty> collectPropertiesToInitialize() { FunctionCodegen.endVisit(codegen.v, "static initializer for package", jetFile);
List<JetProperty> result = Lists.newArrayList();
for (JetDeclaration declaration : jetFile.getDeclarations()) {
if (declaration instanceof JetProperty &&
ImplementationBodyCodegen.shouldInitializeProperty((JetProperty) declaration, typeMapper)) {
result.add((JetProperty) declaration);
}
}
return result;
} }
} }