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.context.ClassContext;
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.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
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.resolve.BindingContext;
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.List;
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;
public abstract class ClassBodyCodegen extends MemberCodegen {
protected final JetClassOrObject myClass;
protected final OwnerKind kind;
protected final ClassDescriptor descriptor;
protected final ClassBuilder v;
private MethodVisitor clInitMethod;
private ExpressionCodegen clInitCodegen;
protected ClassBodyCodegen(
@NotNull JetClassOrObject aClass,
@@ -56,10 +48,9 @@ public abstract class ClassBodyCodegen extends MemberCodegen {
@Nullable MemberCodegen parentCodegen
) {
super(state, parentCodegen, context, v);
descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
myClass = aClass;
this.kind = context.getContextKind();
this.v = v;
kind = context.getContextKind();
descriptor = bindingContext.get(BindingContext.CLASS, aClass);
}
public void generate() {
@@ -69,7 +60,7 @@ public abstract class ClassBodyCodegen extends MemberCodegen {
generateSyntheticParts();
generateStaticInitializer();
completeStaticInitializer();
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) {
return ((JetClass) myClass).getPrimaryConstructorParameters();
}
return Collections.emptyList();
}
private void generateStaticInitializer() {
if (clInitMethod != null) {
createOrGetClInitMethod();
if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
ExpressionCodegen codegen = createOrGetClInitCodegen();
createOrGetClInitMethod().visitInsn(RETURN);
FunctionCodegen.endVisit(codegen.v, "static initializer", myClass);
}
private void completeStaticInitializer() {
if (clInit != null) {
clInit.v.visitInsn(RETURN);
FunctionCodegen.endVisit(clInit.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 org.jetbrains.annotations.NotNull;
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.CodegenContext;
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.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.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.name.SpecialNames;
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 {
protected final FieldOwnerContext context;
private final ClassBuilder builder;
protected final ClassBuilder v;
protected ExpressionCodegen clInit;
private NameGenerator inlineNameGenerator;
@@ -44,11 +52,11 @@ public class MemberCodegen extends ParentCodegenAwareImpl {
@NotNull GenerationState state,
@Nullable MemberCodegen parentCodegen,
@NotNull FieldOwnerContext context,
@Nullable ClassBuilder builder
ClassBuilder builder
) {
super(state, parentCodegen);
this.context = context;
this.builder = builder;
this.v = builder;
}
public void genFunctionOrProperty(
@@ -121,8 +129,7 @@ public class MemberCodegen extends ParentCodegenAwareImpl {
private static void badDescriptor(ClassDescriptor descriptor, ClassBuilderMode mode) {
if (mode != ClassBuilderMode.LIGHT_CLASSES) {
throw new IllegalStateException(
"Generating bad descriptor in ClassBuilderMode = " + mode + ": " + descriptor);
throw new IllegalStateException("Generating bad descriptor in ClassBuilderMode = " + mode + ": " + descriptor);
}
}
@@ -132,15 +139,33 @@ public class MemberCodegen extends ParentCodegenAwareImpl {
@NotNull
public ClassBuilder getBuilder() {
return builder;
return v;
}
@NotNull
public NameGenerator getInlineNameGenerator() {
if (inlineNameGenerator == null) {
String prefix = InlineCodegenUtil.getInlineName(context, typeMapper);
inlineNameGenerator = new NameGenerator(prefix);
}
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 org.jetbrains.annotations.NotNull;
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.FieldOwnerContext;
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.GenerationStateAware;
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.DeserializedPropertyDescriptor;
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.name.FqName;
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 static org.jetbrains.org.objectweb.asm.Opcodes.*;
import static org.jetbrains.jet.codegen.AsmUtil.asmDescByFqNameWithoutInnerClasses;
import static org.jetbrains.jet.codegen.AsmUtil.asmTypeByFqNameWithoutInnerClasses;
import static org.jetbrains.jet.descriptors.serialization.NameSerializationUtil.createNameResolver;
import static org.jetbrains.jet.lang.resolve.java.PackageClassUtils.getPackageClassFqName;
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
public class PackageCodegen extends GenerationStateAware {
@NotNull
@@ -321,7 +324,7 @@ public class PackageCodegen extends GenerationStateAware {
@NotNull
@Override
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.intellij.util.ArrayUtil;
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.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.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.org.objectweb.asm.Type;
import java.util.Collections;
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.lang.resolve.java.JvmAnnotationNames.KotlinSyntheticClass;
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
public class PackagePartCodegen extends MemberCodegen {
private final ClassBuilder v;
private final PackageFragmentDescriptor descriptor;
private final JetFile jetFile;
private final Type packagePartName;
private final FieldOwnerContext context;
private final Type packagePartType;
public PackagePartCodegen(
@NotNull ClassBuilder v,
@NotNull JetFile jetFile,
@NotNull Type packagePartName,
@NotNull Type packagePartType,
@NotNull FieldOwnerContext context,
@NotNull GenerationState state
) {
super(state, null, context, v);
this.v = v;
this.jetFile = jetFile;
this.packagePartName = packagePartName;
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();
this.packagePartType = packagePartType;
}
public void generate() {
v.defineClass(jetFile, V1_6,
ACC_PUBLIC | ACC_FINAL,
packagePartName.getInternalName(),
packagePartType.getInternalName(),
null,
"java/lang/Object",
ArrayUtil.EMPTY_STRING_ARRAY
@@ -89,44 +70,24 @@ public class PackagePartCodegen extends MemberCodegen {
}
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;
MethodVisitor mv = v.newMethod(jetFile, ACC_STATIC, "<clinit>", "()V", null, null);
if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode();
ExpressionCodegen codegen = createOrGetClInitCodegen();
FrameMap frameMap = new FrameMap();
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();
for (JetProperty property : properties) {
ImplementationBodyCodegen.initializeProperty(codegen, bindingContext, property);
}
}
@NotNull
private List<JetProperty> collectPropertiesToInitialize() {
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;
codegen.v.visitInsn(RETURN);
FunctionCodegen.endVisit(codegen.v, "static initializer for package", jetFile);
}
}