From 57f4f664ba0bf785e9903535a4965d786cf13062 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 12 Jul 2011 17:34:05 +0200 Subject: [PATCH] refactored generation of static initializer --- .../jet/codegen/ClassBodyCodegen.java | 26 ++++ .../org/jetbrains/jet/codegen/CodeChunk.java | 10 ++ .../codegen/ImplementationBodyCodegen.java | 114 +++++++++--------- 3 files changed, 95 insertions(+), 55 deletions(-) create mode 100644 idea/src/org/jetbrains/jet/codegen/CodeChunk.java diff --git a/idea/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java b/idea/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java index ed0735204e8..58a6fa5d7d4 100644 --- a/idea/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java @@ -4,8 +4,11 @@ import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; import org.jetbrains.jet.lang.psi.*; import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; +import org.objectweb.asm.commons.InstructionAdapter; +import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -22,6 +25,8 @@ public abstract class ClassBodyCodegen { protected final ClassVisitor v; protected final ClassContext context; + protected final List staticInitializerChunks = new ArrayList(); + public ClassBodyCodegen(JetClassOrObject aClass, ClassContext context, ClassVisitor v, GenerationState state) { this.state = state; descriptor = state.getBindingContext().getClassDescriptor(aClass); @@ -38,6 +43,8 @@ public abstract class ClassBodyCodegen { generateClassBody(); + generateStaticInitializer(); + v.visitEnd(); } @@ -95,4 +102,23 @@ public abstract class ClassBodyCodegen { } return Collections.emptyList(); } + + private void generateStaticInitializer() { + if (staticInitializerChunks.size() > 0) { + final MethodVisitor mv = v.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, + "", "()V", null, null); + mv.visitCode(); + + InstructionAdapter v = new InstructionAdapter(mv); + + for (CodeChunk chunk : staticInitializerChunks) { + chunk.generate(v); + } + + mv.visitInsn(Opcodes.RETURN); + mv.visitMaxs(0, 0); + + mv.visitEnd(); + } + } } diff --git a/idea/src/org/jetbrains/jet/codegen/CodeChunk.java b/idea/src/org/jetbrains/jet/codegen/CodeChunk.java new file mode 100644 index 00000000000..eb0aa420884 --- /dev/null +++ b/idea/src/org/jetbrains/jet/codegen/CodeChunk.java @@ -0,0 +1,10 @@ +package org.jetbrains.jet.codegen; + +import org.objectweb.asm.commons.InstructionAdapter; + +/** + * @author yole + */ +public interface CodeChunk { + void generate(InstructionAdapter v); +} diff --git a/idea/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/idea/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index f013f20e2d9..12870900569 100644 --- a/idea/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -74,20 +74,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { @Override protected void generateSyntheticParts() { - int typeinfoStatic = descriptor.getTypeConstructor().getParameters().size() > 0 ? 0 : Opcodes.ACC_STATIC; - v.visitField(Opcodes.ACC_PRIVATE | typeinfoStatic, "$typeInfo", "Ljet/typeinfo/TypeInfo;", null, null); - - if (isNonLiteralObject()) { - Type type = JetTypeMapper.jetImplementationType(descriptor); - v.visitField(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "$instance", type.getDescriptor(), null, null); - } - final JetClassObject classObject = getClassObject(); - if (classObject != null) { - Type type = Type.getObjectType(state.getTypeMapper().jvmName(classObject)); - v.visitField(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "$classobj", type.getDescriptor(), null, null); - } - - generateStaticInitializer(); + generateFieldForTypeInfo(); + generateFieldForObjectInstance(); + generateFieldForClassObject(); try { generatePrimaryConstructor(); @@ -99,6 +88,62 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { generateGetTypeInfo(); } + private void generateFieldForTypeInfo() { + final boolean typeInfoIsStatic = descriptor.getTypeConstructor().getParameters().size() == 0; + v.visitField(Opcodes.ACC_PRIVATE | (typeInfoIsStatic ? Opcodes.ACC_STATIC : 0), "$typeInfo", + "Ljet/typeinfo/TypeInfo;", null, null); + if (typeInfoIsStatic) { + staticInitializerChunks.add(new CodeChunk() { + @Override + public void generate(InstructionAdapter v) { + JetTypeMapper typeMapper = state.getTypeMapper(); + ClassCodegen.newTypeInfo(v, false, typeMapper.jvmType(descriptor, OwnerKind.INTERFACE)); + v.putstatic(typeMapper.jvmName(descriptor, kind), "$typeInfo", "Ljet/typeinfo/TypeInfo;"); + } + }); + } + } + + private void generateFieldForObjectInstance() { + if (isNonLiteralObject()) { + Type type = JetTypeMapper.jetImplementationType(descriptor); + v.visitField(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "$instance", type.getDescriptor(), null, null); + + staticInitializerChunks.add(new CodeChunk() { + @Override + public void generate(InstructionAdapter v) { + String name = jvmName(); + v.anew(Type.getObjectType(name)); + v.dup(); + v.invokespecial(name, "", "()V"); + v.putstatic(name, "$instance", JetTypeMapper.jetImplementationType(descriptor).getDescriptor()); + } + }); + + } + } + + private void generateFieldForClassObject() { + final JetClassObject classObject = getClassObject(); + if (classObject != null) { + Type type = Type.getObjectType(state.getTypeMapper().jvmName(classObject)); + v.visitField(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "$classobj", type.getDescriptor(), null, null); + + staticInitializerChunks.add(new CodeChunk() { + @Override + public void generate(InstructionAdapter v) { + String name = state.getTypeMapper().jvmName(classObject); + final Type classObjectType = Type.getObjectType(name); + v.anew(classObjectType); + v.dup(); + v.invokespecial(name, "", "()V"); + v.putstatic(state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION), "$classobj", + classObjectType.getDescriptor()); + } + }); + } + } + protected void generatePrimaryConstructor() { ConstructorDescriptor constructorDescriptor = state.getBindingContext().getConstructorDescriptor((JetElement) myClass); if (constructorDescriptor == null && !(myClass instanceof JetObjectDeclaration)) return; @@ -409,47 +454,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { } } - private void generateStaticInitializer() { - boolean needTypeInfo = descriptor.getTypeConstructor().getParameters().size() == 0; - boolean needInstance = isNonLiteralObject(); - JetClassObject classObject = getClassObject(); - if (!needTypeInfo && !needInstance && classObject == null) { - return; - } - final MethodVisitor mv = v.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, - "", "()V", null, null); - mv.visitCode(); - - InstructionAdapter v = new InstructionAdapter(mv); - - if (needTypeInfo) { - JetTypeMapper typeMapper = state.getTypeMapper(); - ClassCodegen.newTypeInfo(v, false, typeMapper.jvmType(descriptor, OwnerKind.INTERFACE)); - v.putstatic(typeMapper.jvmName(descriptor, kind), "$typeInfo", "Ljet/typeinfo/TypeInfo;"); - } - if (needInstance) { - String name = jvmName(); - v.anew(Type.getObjectType(name)); - v.dup(); - v.invokespecial(name, "", "()V"); - v.putstatic(name, "$instance", JetTypeMapper.jetImplementationType(descriptor).getDescriptor()); - } - if (classObject != null) { - String name = state.getTypeMapper().jvmName(classObject); - final Type classObjectType = Type.getObjectType(name); - v.anew(classObjectType); - v.dup(); - v.invokespecial(name, "", "()V"); - v.putstatic(state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION), "$classobj", - classObjectType.getDescriptor()); - } - - mv.visitInsn(Opcodes.RETURN); - mv.visitMaxs(0, 0); - - mv.visitEnd(); - } - @Nullable private JetClassObject getClassObject() { return myClass instanceof JetClass ? ((JetClass) myClass).getClassObject() : null;