refactored generation of static initializer
This commit is contained in:
@@ -4,8 +4,11 @@ import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
|||||||
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
|
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.objectweb.asm.ClassVisitor;
|
import org.objectweb.asm.ClassVisitor;
|
||||||
|
import org.objectweb.asm.MethodVisitor;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
|
import org.objectweb.asm.commons.InstructionAdapter;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -22,6 +25,8 @@ public abstract class ClassBodyCodegen {
|
|||||||
protected final ClassVisitor v;
|
protected final ClassVisitor v;
|
||||||
protected final ClassContext context;
|
protected final ClassContext context;
|
||||||
|
|
||||||
|
protected final List<CodeChunk> staticInitializerChunks = new ArrayList<CodeChunk>();
|
||||||
|
|
||||||
public ClassBodyCodegen(JetClassOrObject aClass, ClassContext context, ClassVisitor v, GenerationState state) {
|
public ClassBodyCodegen(JetClassOrObject aClass, ClassContext context, ClassVisitor v, GenerationState state) {
|
||||||
this.state = state;
|
this.state = state;
|
||||||
descriptor = state.getBindingContext().getClassDescriptor(aClass);
|
descriptor = state.getBindingContext().getClassDescriptor(aClass);
|
||||||
@@ -38,6 +43,8 @@ public abstract class ClassBodyCodegen {
|
|||||||
|
|
||||||
generateClassBody();
|
generateClassBody();
|
||||||
|
|
||||||
|
generateStaticInitializer();
|
||||||
|
|
||||||
v.visitEnd();
|
v.visitEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,4 +102,23 @@ public abstract class ClassBodyCodegen {
|
|||||||
}
|
}
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void generateStaticInitializer() {
|
||||||
|
if (staticInitializerChunks.size() > 0) {
|
||||||
|
final MethodVisitor mv = v.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC,
|
||||||
|
"<clinit>", "()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();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package org.jetbrains.jet.codegen;
|
||||||
|
|
||||||
|
import org.objectweb.asm.commons.InstructionAdapter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author yole
|
||||||
|
*/
|
||||||
|
public interface CodeChunk {
|
||||||
|
void generate(InstructionAdapter v);
|
||||||
|
}
|
||||||
@@ -74,20 +74,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void generateSyntheticParts() {
|
protected void generateSyntheticParts() {
|
||||||
int typeinfoStatic = descriptor.getTypeConstructor().getParameters().size() > 0 ? 0 : Opcodes.ACC_STATIC;
|
generateFieldForTypeInfo();
|
||||||
v.visitField(Opcodes.ACC_PRIVATE | typeinfoStatic, "$typeInfo", "Ljet/typeinfo/TypeInfo;", null, null);
|
generateFieldForObjectInstance();
|
||||||
|
generateFieldForClassObject();
|
||||||
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();
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
generatePrimaryConstructor();
|
generatePrimaryConstructor();
|
||||||
@@ -99,6 +88,62 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
generateGetTypeInfo();
|
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, "<init>", "()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, "<init>", "()V");
|
||||||
|
v.putstatic(state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION), "$classobj",
|
||||||
|
classObjectType.getDescriptor());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected void generatePrimaryConstructor() {
|
protected void generatePrimaryConstructor() {
|
||||||
ConstructorDescriptor constructorDescriptor = state.getBindingContext().getConstructorDescriptor((JetElement) myClass);
|
ConstructorDescriptor constructorDescriptor = state.getBindingContext().getConstructorDescriptor((JetElement) myClass);
|
||||||
if (constructorDescriptor == null && !(myClass instanceof JetObjectDeclaration)) return;
|
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,
|
|
||||||
"<clinit>", "()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, "<init>", "()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, "<init>", "()V");
|
|
||||||
v.putstatic(state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION), "$classobj",
|
|
||||||
classObjectType.getDescriptor());
|
|
||||||
}
|
|
||||||
|
|
||||||
mv.visitInsn(Opcodes.RETURN);
|
|
||||||
mv.visitMaxs(0, 0);
|
|
||||||
|
|
||||||
mv.visitEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private JetClassObject getClassObject() {
|
private JetClassObject getClassObject() {
|
||||||
return myClass instanceof JetClass ? ((JetClass) myClass).getClassObject() : null;
|
return myClass instanceof JetClass ? ((JetClass) myClass).getClassObject() : null;
|
||||||
|
|||||||
Reference in New Issue
Block a user