Wrap ASM class generation so we can attribute generated classes with PSI origins when building kotlin-as-seen-from-java model

This commit is contained in:
Maxim Shafirov
2011-11-02 18:24:53 +03:00
parent 99d19a2f27
commit 20233da7cf
12 changed files with 206 additions and 139 deletions
@@ -1,10 +1,10 @@
package org.jetbrains.jet.codegen; package org.jetbrains.jet.codegen;
import com.intellij.psi.PsiElement;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor; 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.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes; import org.objectweb.asm.Opcodes;
import org.objectweb.asm.commons.InstructionAdapter; import org.objectweb.asm.commons.InstructionAdapter;
@@ -23,12 +23,12 @@ public abstract class ClassBodyCodegen {
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 ClassVisitor v; protected final ClassBuilder v;
protected final ClassContext context; protected final ClassContext context;
protected final List<CodeChunk> staticInitializerChunks = new ArrayList<CodeChunk>(); protected final List<CodeChunk> staticInitializerChunks = new ArrayList<CodeChunk>();
public ClassBodyCodegen(JetClassOrObject aClass, ClassContext context, ClassVisitor v, GenerationState state) { public ClassBodyCodegen(JetClassOrObject aClass, ClassContext context, ClassBuilder v, GenerationState state) {
this.state = state; this.state = state;
descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass); descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
myClass = aClass; myClass = aClass;
@@ -46,7 +46,7 @@ public abstract class ClassBodyCodegen {
generateStaticInitializer(); generateStaticInitializer();
v.visitEnd(); v.done();
} }
protected abstract void generateDeclaration(); protected abstract void generateDeclaration();
@@ -62,7 +62,7 @@ public abstract class ClassBodyCodegen {
generateDeclaration(propertyCodegen, declaration, functionCodegen); generateDeclaration(propertyCodegen, declaration, functionCodegen);
} }
generatePrimaryConstructorProperties(propertyCodegen); generatePrimaryConstructorProperties(propertyCodegen, myClass);
} }
protected void generateDeclaration(PropertyCodegen propertyCodegen, JetDeclaration declaration, FunctionCodegen functionCodegen) { protected void generateDeclaration(PropertyCodegen propertyCodegen, JetDeclaration declaration, FunctionCodegen functionCodegen) {
@@ -82,20 +82,20 @@ public abstract class ClassBodyCodegen {
functionCodegen.gen(declaration); functionCodegen.gen(declaration);
} }
private void generatePrimaryConstructorProperties(PropertyCodegen propertyCodegen) { private void generatePrimaryConstructorProperties(PropertyCodegen propertyCodegen, PsiElement origin) {
OwnerKind kind = context.getContextKind(); OwnerKind kind = context.getContextKind();
for (JetParameter p : getPrimaryConstructorParameters()) { for (JetParameter p : getPrimaryConstructorParameters()) {
if (p.getValOrVarNode() != null) { if (p.getValOrVarNode() != null) {
PropertyDescriptor propertyDescriptor = state.getBindingContext().get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, p); PropertyDescriptor propertyDescriptor = state.getBindingContext().get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, p);
if (propertyDescriptor != null) { if (propertyDescriptor != null) {
propertyCodegen.generateDefaultGetter(propertyDescriptor, Opcodes.ACC_PUBLIC); propertyCodegen.generateDefaultGetter(propertyDescriptor, Opcodes.ACC_PUBLIC, p);
if (propertyDescriptor.isVar()) { if (propertyDescriptor.isVar()) {
propertyCodegen.generateDefaultSetter(propertyDescriptor, Opcodes.ACC_PUBLIC); propertyCodegen.generateDefaultSetter(propertyDescriptor, Opcodes.ACC_PUBLIC, origin);
} }
//noinspection ConstantConditions //noinspection ConstantConditions
if (!(kind instanceof OwnerKind.DelegateKind) && state.getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor)) { if (!(kind instanceof OwnerKind.DelegateKind) && state.getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor)) {
v.visitField(Opcodes.ACC_PRIVATE, p.getName(), state.getTypeMapper().mapType(propertyDescriptor.getOutType()).getDescriptor(), null, null); v.newField(p, Opcodes.ACC_PRIVATE, p.getName(), state.getTypeMapper().mapType(propertyDescriptor.getOutType()).getDescriptor(), null, null);
} }
} }
} }
@@ -111,8 +111,8 @@ public abstract class ClassBodyCodegen {
private void generateStaticInitializer() { private void generateStaticInitializer() {
if (staticInitializerChunks.size() > 0) { if (staticInitializerChunks.size() > 0) {
final MethodVisitor mv = v.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, final MethodVisitor mv = v.newMethod(null, Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC,
"<clinit>", "()V", null, null); "<clinit>", "()V", null, null);
mv.visitCode(); mv.visitCode();
InstructionAdapter v = new InstructionAdapter(mv); InstructionAdapter v = new InstructionAdapter(mv);
@@ -0,0 +1,59 @@
/*
* @author max
*/
package org.jetbrains.jet.codegen;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.Nullable;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;
public class ClassBuilder {
private final ClassVisitor v;
public ClassBuilder(ClassVisitor v) {
this.v = v;
}
public FieldVisitor newField(@Nullable PsiElement origin,
int access,
String name,
String desc,
String signature,
Object value) {
return v.visitField(access, name, desc, signature, value);
}
public MethodVisitor newMethod(@Nullable PsiElement origin,
int access,
String name,
String desc,
@Nullable String signature,
@Nullable String[] exceptions) {
return v.visitMethod(access, name, desc, signature, exceptions);
}
public AnnotationVisitor newAnnotation(PsiElement origin,
String desc,
boolean visible) {
return v.visitAnnotation(desc, visible);
}
public void done() {
v.visitEnd();
}
public ClassVisitor getVisitor() {
return v;
}
public void defineClass(int version, int access, String name, String signature, String superName, String[] interfaces) {
v.visit(version, access, name, signature, superName, interfaces);
}
public void visitSource(String name, String debug) {
v.visitSource(name, debug);
}
}
@@ -3,7 +3,6 @@ package org.jetbrains.jet.codegen;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
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.objectweb.asm.ClassVisitor;
/** /**
* @author max * @author max
@@ -33,7 +32,7 @@ public class ClassCodegen {
private void generateImplementation(ClassContext parentContext, JetClassOrObject aClass, OwnerKind kind) { private void generateImplementation(ClassContext parentContext, JetClassOrObject aClass, OwnerKind kind) {
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass); ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
ClassVisitor v = state.forClassImplementation(descriptor); ClassBuilder v = state.forClassImplementation(descriptor);
new ImplementationBodyCodegen(aClass, parentContext.intoClass(null, descriptor, kind), v, state).generate(); new ImplementationBodyCodegen(aClass, parentContext.intoClass(null, descriptor, kind), v, state).generate();
if(aClass instanceof JetClass && ((JetClass)aClass).isTrait()) { if(aClass instanceof JetClass && ((JetClass)aClass).isTrait()) {
@@ -17,7 +17,7 @@ public class ClassFileFactory {
private final Project project; private final Project project;
private final boolean isText; private final boolean isText;
private final Map<String, NamespaceCodegen> ns2codegen = new HashMap<String, NamespaceCodegen>(); private final Map<String, NamespaceCodegen> ns2codegen = new HashMap<String, NamespaceCodegen>();
private final Map<String, ClassVisitor> generators = new LinkedHashMap<String, ClassVisitor>(); private final Map<String, ClassBuilder> generators = new LinkedHashMap<String, ClassBuilder>();
private boolean isDone = false; private boolean isDone = false;
public final GenerationState state; public final GenerationState state;
@@ -27,7 +27,7 @@ public class ClassFileFactory {
this.state = state; this.state = state;
} }
ClassVisitor newVisitor(String filePath) { ClassBuilder newVisitor(String filePath) {
ClassVisitor visitor; ClassVisitor visitor;
if (isText) { if (isText) {
visitor = new TraceClassVisitor(new PrintWriter(new StringWriter())); visitor = new TraceClassVisitor(new PrintWriter(new StringWriter()));
@@ -36,11 +36,12 @@ public class ClassFileFactory {
visitor = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); visitor = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
} }
generators.put(filePath, visitor); final ClassBuilder answer = new ClassBuilder(visitor);
return visitor; generators.put(filePath, answer);
return answer;
} }
ClassVisitor forAnonymousSubclass(String className) { ClassBuilder forAnonymousSubclass(String className) {
return newVisitor(className + ".class"); return newVisitor(className + ".class");
} }
@@ -49,8 +50,8 @@ public class ClassFileFactory {
String fqName = namespace.getFQName(); String fqName = namespace.getFQName();
NamespaceCodegen codegen = ns2codegen.get(fqName); NamespaceCodegen codegen = ns2codegen.get(fqName);
if (codegen == null) { if (codegen == null) {
final ClassVisitor classVisitor = newVisitor(NamespaceCodegen.getJVMClassName(fqName) + ".class"); final ClassBuilder builder = newVisitor(NamespaceCodegen.getJVMClassName(fqName) + ".class");
codegen = new NamespaceCodegen(classVisitor, fqName, state, namespace.getContainingFile()); codegen = new NamespaceCodegen(builder, fqName, state, namespace.getContainingFile());
ns2codegen.put(fqName, codegen); ns2codegen.put(fqName, codegen);
} }
@@ -71,7 +72,7 @@ public class ClassFileFactory {
done(); done();
TraceClassVisitor visitor = (TraceClassVisitor) generators.get(file); TraceClassVisitor visitor = (TraceClassVisitor) generators.get(file).getVisitor();
StringWriter writer = new StringWriter(); StringWriter writer = new StringWriter();
visitor.print(new PrintWriter(writer)); visitor.print(new PrintWriter(writer));
@@ -84,7 +85,7 @@ public class ClassFileFactory {
done(); done();
ClassWriter visitor = (ClassWriter) generators.get(file); ClassWriter visitor = (ClassWriter) generators.get(file).getVisitor();
return visitor.toByteArray(); return visitor.toByteArray();
} }
@@ -5,13 +5,18 @@
package org.jetbrains.jet.codegen; package org.jetbrains.jet.codegen;
import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Pair;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
import org.jetbrains.jet.lang.psi.JetFunctionLiteral; import org.jetbrains.jet.lang.psi.JetFunctionLiteral;
import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression; import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
import org.objectweb.asm.*; import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter; import org.objectweb.asm.commons.InstructionAdapter;
import org.objectweb.asm.commons.Method; import org.objectweb.asm.commons.Method;
import org.objectweb.asm.signature.SignatureWriter; import org.objectweb.asm.signature.SignatureWriter;
@@ -44,7 +49,7 @@ public class ClosureCodegen extends FunctionOrClosureCodegen {
} }
public GeneratedAnonymousClassDescriptor gen(JetFunctionLiteralExpression fun) { public GeneratedAnonymousClassDescriptor gen(JetFunctionLiteralExpression fun) {
final Pair<String, ClassVisitor> nameAndVisitor = state.forAnonymousSubclass(fun); final Pair<String, ClassBuilder> nameAndVisitor = state.forAnonymousSubclass(fun);
final FunctionDescriptor funDescriptor = (FunctionDescriptor) state.getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, fun); final FunctionDescriptor funDescriptor = (FunctionDescriptor) state.getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, fun);
@@ -63,32 +68,32 @@ public class ClosureCodegen extends FunctionOrClosureCodegen {
appendType(signatureWriter, funDescriptor.getReturnType(), '='); appendType(signatureWriter, funDescriptor.getReturnType(), '=');
signatureWriter.visitEnd(); signatureWriter.visitEnd();
cv.visit(V1_6, cv.defineClass(V1_6,
ACC_PUBLIC, ACC_PUBLIC,
name, name,
null, null,
funClass, funClass,
new String[0] new String[0]
); );
cv.visitSource(fun.getContainingFile().getName(), null); cv.visitSource(fun.getContainingFile().getName(), null);
generateBridge(name, funDescriptor, cv); generateBridge(name, funDescriptor, fun, cv);
captureThis = generateBody(funDescriptor, cv, fun.getFunctionLiteral()); captureThis = generateBody(funDescriptor, cv, fun.getFunctionLiteral());
final Type enclosingType = context.enclosingClassType(state.getTypeMapper()); final Type enclosingType = context.enclosingClassType(state.getTypeMapper());
if (enclosingType == null) captureThis = false; if (enclosingType == null) captureThis = false;
final Method constructor = generateConstructor(funClass, captureThis, funDescriptor.getReturnType()); final Method constructor = generateConstructor(funClass, captureThis, fun, funDescriptor.getReturnType());
if (captureThis) { if (captureThis) {
cv.visitField(0, "this$0", enclosingType.getDescriptor(), null, null); cv.newField(fun, 0, "this$0", enclosingType.getDescriptor(), null, null);
} }
if(isConst()) { if(isConst()) {
generateConstInstance(); generateConstInstance(fun);
} }
cv.visitEnd(); cv.done();
final GeneratedAnonymousClassDescriptor answer = new GeneratedAnonymousClassDescriptor(name, constructor, captureThis); final GeneratedAnonymousClassDescriptor answer = new GeneratedAnonymousClassDescriptor(name, constructor, captureThis);
for (DeclarationDescriptor descriptor : closure.keySet()) { for (DeclarationDescriptor descriptor : closure.keySet()) {
@@ -98,10 +103,10 @@ public class ClosureCodegen extends FunctionOrClosureCodegen {
return answer; return answer;
} }
private void generateConstInstance() { private void generateConstInstance(JetFunctionLiteralExpression fun) {
cv.visitField(ACC_PRIVATE| ACC_STATIC, "$instance", "Ljava/lang/ref/SoftReference;", null, null); cv.newField(fun, ACC_PRIVATE | ACC_STATIC, "$instance", "Ljava/lang/ref/SoftReference;", null, null);
MethodVisitor mv = cv.visitMethod(ACC_PUBLIC | ACC_STATIC, "$getInstance", "()L" + name + ";", null, new String[0]); MethodVisitor mv = cv.newMethod(fun, ACC_PUBLIC | ACC_STATIC, "$getInstance", "()L" + name + ";", null, new String[0]);
mv.visitCode(); mv.visitCode();
mv.visitFieldInsn(GETSTATIC, name, "$instance", "Ljava/lang/ref/SoftReference;"); mv.visitFieldInsn(GETSTATIC, name, "$instance", "Ljava/lang/ref/SoftReference;");
mv.visitInsn(DUP); mv.visitInsn(DUP);
@@ -140,21 +145,21 @@ public class ClosureCodegen extends FunctionOrClosureCodegen {
mv.visitEnd(); mv.visitEnd();
} }
private boolean generateBody(FunctionDescriptor funDescriptor, ClassVisitor cv, JetFunctionLiteral body) { private boolean generateBody(FunctionDescriptor funDescriptor, ClassBuilder cv, JetFunctionLiteral body) {
final ClassContext closureContext = context.intoClosure(name, this); final ClassContext closureContext = context.intoClosure(name, this);
FunctionCodegen fc = new FunctionCodegen(closureContext, cv, state); FunctionCodegen fc = new FunctionCodegen(closureContext, cv, state);
fc.generateMethod(body, invokeSignature(funDescriptor), funDescriptor); fc.generateMethod(body, invokeSignature(funDescriptor), funDescriptor);
return closureContext.isThisWasUsed(); return closureContext.isThisWasUsed();
} }
private void generateBridge(String className, FunctionDescriptor funDescriptor, ClassVisitor cv) { private void generateBridge(String className, FunctionDescriptor funDescriptor, JetFunctionLiteralExpression fun, ClassBuilder cv) {
final Method bridge = erasedInvokeSignature(funDescriptor); final Method bridge = erasedInvokeSignature(funDescriptor);
final Method delegate = invokeSignature(funDescriptor); final Method delegate = invokeSignature(funDescriptor);
if(bridge.getDescriptor().equals(delegate.getDescriptor())) if(bridge.getDescriptor().equals(delegate.getDescriptor()))
return; return;
final MethodVisitor mv = cv.visitMethod(ACC_PUBLIC, "invoke", bridge.getDescriptor(), state.getTypeMapper().genericSignature(funDescriptor), new String[0]); final MethodVisitor mv = cv.newMethod(fun, ACC_PUBLIC, "invoke", bridge.getDescriptor(), state.getTypeMapper().genericSignature(funDescriptor), new String[0]);
mv.visitCode(); mv.visitCode();
InstructionAdapter iv = new InstructionAdapter(mv); InstructionAdapter iv = new InstructionAdapter(mv);
@@ -185,7 +190,7 @@ public class ClosureCodegen extends FunctionOrClosureCodegen {
mv.visitEnd(); mv.visitEnd();
} }
private Method generateConstructor(String funClass, boolean captureThis, JetType returnType) { private Method generateConstructor(String funClass, boolean captureThis, JetFunctionLiteralExpression fun, JetType returnType) {
int argCount = closure.size(); int argCount = closure.size();
if (captureThis) { if (captureThis) {
@@ -208,7 +213,7 @@ public class ClosureCodegen extends FunctionOrClosureCodegen {
} }
final Method constructor = new Method("<init>", Type.VOID_TYPE, argTypes); final Method constructor = new Method("<init>", Type.VOID_TYPE, argTypes);
final MethodVisitor mv = cv.visitMethod(ACC_PUBLIC, "<init>", constructor.getDescriptor(), null, new String[0]); final MethodVisitor mv = cv.newMethod(fun, ACC_PUBLIC, "<init>", constructor.getDescriptor(), null, new String[0]);
mv.visitCode(); mv.visitCode();
InstructionAdapter iv = new InstructionAdapter(mv); InstructionAdapter iv = new InstructionAdapter(mv);
ExpressionCodegen expressionCodegen = new ExpressionCodegen(mv, null, Type.VOID_TYPE, context, state); ExpressionCodegen expressionCodegen = new ExpressionCodegen(mv, null, Type.VOID_TYPE, context, state);
@@ -4,7 +4,10 @@ import com.intellij.psi.PsiElement;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
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.objectweb.asm.*; import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter; import org.objectweb.asm.commons.InstructionAdapter;
import org.objectweb.asm.commons.Method; import org.objectweb.asm.commons.Method;
@@ -20,10 +23,10 @@ import static org.objectweb.asm.Opcodes.*;
*/ */
public class FunctionCodegen { public class FunctionCodegen {
private final ClassContext owner; private final ClassContext owner;
private final ClassVisitor v; private final ClassBuilder v;
private final GenerationState state; private final GenerationState state;
public FunctionCodegen(ClassContext owner, ClassVisitor v, GenerationState state) { public FunctionCodegen(ClassContext owner, ClassBuilder v, GenerationState state) {
this.owner = owner; this.owner = owner;
this.v = v; this.v = v;
this.state = state; this.state = state;
@@ -39,13 +42,13 @@ public class FunctionCodegen {
ClassContext funContext = owner.intoFunction(functionDescriptor); ClassContext funContext = owner.intoFunction(functionDescriptor);
final JetExpression bodyExpression = f.getBodyExpression(); final JetExpression bodyExpression = f.getBodyExpression();
generatedMethod(bodyExpression, jvmMethod, funContext, functionDescriptor); generatedMethod(bodyExpression, jvmMethod, funContext, functionDescriptor, f);
} }
private void generatedMethod(JetExpression bodyExpressions, private void generatedMethod(JetExpression bodyExpressions,
Method jvmSignature, Method jvmSignature,
ClassContext context, ClassContext context,
FunctionDescriptor functionDescriptor) FunctionDescriptor functionDescriptor, JetDeclarationWithBody fun)
{ {
List<ValueParameterDescriptor> paramDescrs = functionDescriptor.getValueParameters(); List<ValueParameterDescriptor> paramDescrs = functionDescriptor.getValueParameters();
List<TypeParameterDescriptor> typeParameters = functionDescriptor.getTypeParameters(); List<TypeParameterDescriptor> typeParameters = functionDescriptor.getTypeParameters();
@@ -62,7 +65,7 @@ public class FunctionCodegen {
boolean isAbstract = !isStatic && (bodyExpressions == null || CodegenUtil.isInterface(functionDescriptor.getContainingDeclaration())); boolean isAbstract = !isStatic && (bodyExpressions == null || CodegenUtil.isInterface(functionDescriptor.getContainingDeclaration()));
if (isAbstract) flags |= ACC_ABSTRACT; if (isAbstract) flags |= ACC_ABSTRACT;
final MethodVisitor mv = v.visitMethod(flags, jvmSignature.getName(), jvmSignature.getDescriptor(), null, null); final MethodVisitor mv = v.newMethod(fun, flags, jvmSignature.getName(), jvmSignature.getDescriptor(), null, null);
if(kind != OwnerKind.TRAIT_IMPL) { if(kind != OwnerKind.TRAIT_IMPL) {
int start = functionDescriptor.getReceiverParameter().exists() ? 1 : 0; int start = functionDescriptor.getReceiverParameter().exists() ? 1 : 0;
for(int i = 0; i != paramDescrs.size(); ++i) { for(int i = 0; i != paramDescrs.size(); ++i) {
@@ -135,7 +138,7 @@ public class FunctionCodegen {
generateDefaultIfNeeded(context, state, v, jvmSignature, functionDescriptor, kind); generateDefaultIfNeeded(context, state, v, jvmSignature, functionDescriptor, kind);
} }
static void generateBridgeIfNeeded(ClassContext owner, GenerationState state, ClassVisitor v, Method jvmSignature, FunctionDescriptor functionDescriptor, OwnerKind kind) { static void generateBridgeIfNeeded(ClassContext owner, GenerationState state, ClassBuilder v, Method jvmSignature, FunctionDescriptor functionDescriptor, OwnerKind kind) {
Set<? extends FunctionDescriptor> overriddenFunctions = functionDescriptor.getOverriddenDescriptors(); Set<? extends FunctionDescriptor> overriddenFunctions = functionDescriptor.getOverriddenDescriptors();
if(kind != OwnerKind.TRAIT_IMPL) { if(kind != OwnerKind.TRAIT_IMPL) {
for (FunctionDescriptor overriddenFunction : overriddenFunctions) { for (FunctionDescriptor overriddenFunction : overriddenFunctions) {
@@ -146,7 +149,7 @@ public class FunctionCodegen {
} }
} }
static void generateDefaultIfNeeded(ClassContext owner, GenerationState state, ClassVisitor v, Method jvmSignature, FunctionDescriptor functionDescriptor, OwnerKind kind) { static void generateDefaultIfNeeded(ClassContext owner, GenerationState state, ClassBuilder v, Method jvmSignature, FunctionDescriptor functionDescriptor, OwnerKind kind) {
DeclarationDescriptor contextClass = owner.getContextClass(); DeclarationDescriptor contextClass = owner.getContextClass();
if(kind != OwnerKind.TRAIT_IMPL) { if(kind != OwnerKind.TRAIT_IMPL) {
@@ -187,7 +190,7 @@ public class FunctionCodegen {
String descriptor = jvmSignature.getDescriptor().replace(")","I)"); String descriptor = jvmSignature.getDescriptor().replace(")","I)");
if(!isStatic) if(!isStatic)
descriptor = descriptor.replace("(","(L" + ownerInternalName + ";"); descriptor = descriptor.replace("(","(L" + ownerInternalName + ";");
final MethodVisitor mv = v.visitMethod(flags| ACC_STATIC, jvmSignature.getName() + "$default", descriptor, null, null); final MethodVisitor mv = v.newMethod(null, flags | ACC_STATIC, jvmSignature.getName() + "$default", descriptor, null, null);
InstructionAdapter iv = new InstructionAdapter(mv); InstructionAdapter iv = new InstructionAdapter(mv);
mv.visitCode(); mv.visitCode();
@@ -287,14 +290,14 @@ public class FunctionCodegen {
} }
} }
private static void checkOverride(ClassContext owner, GenerationState state, ClassVisitor v, Method jvmSignature, FunctionDescriptor functionDescriptor, FunctionDescriptor overriddenFunction) { private static void checkOverride(ClassContext owner, GenerationState state, ClassBuilder v, Method jvmSignature, FunctionDescriptor functionDescriptor, FunctionDescriptor overriddenFunction) {
Type type1 = state.getTypeMapper().mapType(overriddenFunction.getOriginal().getReturnType()); Type type1 = state.getTypeMapper().mapType(overriddenFunction.getOriginal().getReturnType());
Type type2 = state.getTypeMapper().mapType(functionDescriptor.getReturnType()); Type type2 = state.getTypeMapper().mapType(functionDescriptor.getReturnType());
if(!type1.equals(type2)) { if(!type1.equals(type2)) {
Method overriden = state.getTypeMapper().mapSignature(overriddenFunction.getName(), overriddenFunction.getOriginal()); Method overriden = state.getTypeMapper().mapSignature(overriddenFunction.getName(), overriddenFunction.getOriginal());
int flags = ACC_PUBLIC; // TODO. int flags = ACC_PUBLIC; // TODO.
final MethodVisitor mv = v.visitMethod(flags, jvmSignature.getName(), overriden.getDescriptor(), null, null); final MethodVisitor mv = v.newMethod(null, flags, jvmSignature.getName(), overriden.getDescriptor(), null, null);
mv.visitCode(); mv.visitCode();
Type[] argTypes = jvmSignature.getArgumentTypes(); Type[] argTypes = jvmSignature.getArgumentTypes();
@@ -2,7 +2,6 @@ package org.jetbrains.jet.codegen;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.VariableDescriptor; import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Opcodes; import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type; import org.objectweb.asm.Type;
@@ -18,7 +17,7 @@ public class FunctionOrClosureCodegen {
public final GenerationState state; public final GenerationState state;
protected final ExpressionCodegen exprContext; protected final ExpressionCodegen exprContext;
protected final ClassContext context; protected final ClassContext context;
protected ClassVisitor cv = null; protected ClassBuilder cv = null;
public String name = null; public String name = null;
protected Map<DeclarationDescriptor, EnclosedValueDescriptor> closure = new LinkedHashMap<DeclarationDescriptor, EnclosedValueDescriptor>(); protected Map<DeclarationDescriptor, EnclosedValueDescriptor> closure = new LinkedHashMap<DeclarationDescriptor, EnclosedValueDescriptor>();
@@ -46,7 +45,7 @@ public class FunctionOrClosureCodegen {
final String fieldName = "$" + (closure.size() + 1); // + "$" + vd.getName(); final String fieldName = "$" + (closure.size() + 1); // + "$" + vd.getName();
StackValue innerValue = sharedVarType != null ? StackValue.fieldForSharedVar(localType, name, fieldName) : StackValue.field(type, name, fieldName, false); StackValue innerValue = sharedVarType != null ? StackValue.fieldForSharedVar(localType, name, fieldName) : StackValue.field(type, name, fieldName, false);
cv.visitField(Opcodes.ACC_PUBLIC, fieldName, type.getDescriptor(), null, null); cv.newField(null, Opcodes.ACC_PUBLIC, fieldName, type.getDescriptor(), null, null);
answer = new EnclosedValueDescriptor(d, innerValue, outerValue); answer = new EnclosedValueDescriptor(d, innerValue, outerValue);
closure.put(d, answer); closure.put(d, answer);
@@ -15,8 +15,6 @@ import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.java.JavaDefaultImports; import org.jetbrains.jet.lang.resolve.java.JavaDefaultImports;
import org.jetbrains.jet.lang.types.JetStandardLibrary; import org.jetbrains.jet.lang.types.JetStandardLibrary;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.commons.Method;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@@ -61,26 +59,21 @@ public class GenerationState {
return intrinsics; return intrinsics;
} }
public ClassVisitor forClassInterface(ClassDescriptor aClass) {
return factory.newVisitor(JetTypeMapper.jvmNameForInterface(aClass) + ".class");
}
public ClassCodegen forClass() { public ClassCodegen forClass() {
return new ClassCodegen(this); return new ClassCodegen(this);
} }
public ClassVisitor forClassImplementation(ClassDescriptor aClass) { public ClassBuilder forClassImplementation(ClassDescriptor aClass) {
return factory.newVisitor(typeMapper.jvmName(aClass, OwnerKind.IMPLEMENTATION) + ".class"); return factory.newVisitor(typeMapper.jvmName(aClass, OwnerKind.IMPLEMENTATION) + ".class");
} }
public ClassVisitor forTraitImplementation(ClassDescriptor aClass) { public ClassBuilder forTraitImplementation(ClassDescriptor aClass) {
return factory.newVisitor(typeMapper.jvmName(aClass, OwnerKind.TRAIT_IMPL) + ".class"); return factory.newVisitor(typeMapper.jvmName(aClass, OwnerKind.TRAIT_IMPL) + ".class");
} }
public Pair<String, ClassVisitor> forAnonymousSubclass(JetExpression expression) { public Pair<String, ClassBuilder> forAnonymousSubclass(JetExpression expression) {
String className = typeMapper.classNameForAnonymousClass(expression); String className = typeMapper.classNameForAnonymousClass(expression);
ClassVisitor visitor = factory.forAnonymousSubclass(className); return Pair.create(className, factory.forAnonymousSubclass(className));
return Pair.create(className, visitor);
} }
public NamespaceCodegen forNamespace(JetNamespace namespace) { public NamespaceCodegen forNamespace(JetNamespace namespace) {
@@ -123,7 +116,7 @@ public class GenerationState {
public GeneratedAnonymousClassDescriptor generateObjectLiteral(JetObjectLiteralExpression literal, FunctionOrClosureCodegen closure) { public GeneratedAnonymousClassDescriptor generateObjectLiteral(JetObjectLiteralExpression literal, FunctionOrClosureCodegen closure) {
JetObjectDeclaration objectDeclaration = literal.getObjectDeclaration(); JetObjectDeclaration objectDeclaration = literal.getObjectDeclaration();
Pair<String, ClassVisitor> nameAndVisitor = forAnonymousSubclass(objectDeclaration); Pair<String, ClassBuilder> nameAndVisitor = forAnonymousSubclass(objectDeclaration);
closure.cv = nameAndVisitor.getSecond(); closure.cv = nameAndVisitor.getSecond();
closure.name = nameAndVisitor.getFirst(); closure.name = nameAndVisitor.getFirst();
@@ -11,7 +11,10 @@ import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeProjection; import org.jetbrains.jet.lang.types.TypeProjection;
import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.lexer.JetTokens;
import org.objectweb.asm.*; import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter; import org.objectweb.asm.commons.InstructionAdapter;
import org.objectweb.asm.commons.Method; import org.objectweb.asm.commons.Method;
@@ -26,7 +29,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
private JetDelegationSpecifier superCall; private JetDelegationSpecifier superCall;
private String superClass = "java/lang/Object"; private String superClass = "java/lang/Object";
public ImplementationBodyCodegen(JetClassOrObject aClass, ClassContext context, ClassVisitor v, GenerationState state) { public ImplementationBodyCodegen(JetClassOrObject aClass, ClassContext context, ClassBuilder v, GenerationState state) {
super(aClass, context, v, state); super(aClass, context, v, state);
} }
@@ -89,21 +92,23 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
} }
} }
v.visit(Opcodes.V1_6, v.defineClass(Opcodes.V1_6,
Opcodes.ACC_PUBLIC | (isAbstract ? Opcodes.ACC_ABSTRACT : 0) | (isInterface ? Opcodes.ACC_INTERFACE : 0), Opcodes.ACC_PUBLIC | (isAbstract ? Opcodes.ACC_ABSTRACT : 0) | (isInterface
jvmName(), ? Opcodes.ACC_INTERFACE
null, : 0),
superClass, jvmName(),
interfaces.toArray(new String[interfaces.size()]) null,
superClass,
interfaces.toArray(new String[interfaces.size()])
); );
v.visitSource(myClass.getContainingFile().getName(), null); v.visitSource(myClass.getContainingFile().getName(), null);
if(descriptor.getContainingDeclaration() instanceof ClassDescriptor) { if(descriptor.getContainingDeclaration() instanceof ClassDescriptor) {
v.visitOuterClass(state.getTypeMapper().jvmType((ClassDescriptor) descriptor.getContainingDeclaration(), OwnerKind.IMPLEMENTATION).getInternalName(), null, null); v.getVisitor().visitOuterClass(state.getTypeMapper().jvmType((ClassDescriptor) descriptor.getContainingDeclaration(), OwnerKind.IMPLEMENTATION).getInternalName(), null, null);
} }
if(myClass instanceof JetClass) { if(myClass instanceof JetClass) {
AnnotationVisitor annotationVisitor = v.visitAnnotation("Ljet/typeinfo/JetSignature;", true); AnnotationVisitor annotationVisitor = v.newAnnotation(myClass, "Ljet/typeinfo/JetSignature;", true);
annotationVisitor.visit("value", SignatureUtil.classToSignature((JetClass)myClass, state.getBindingContext(), state.getTypeMapper())); annotationVisitor.visit("value", SignatureUtil.classToSignature((JetClass)myClass, state.getBindingContext(), state.getTypeMapper()));
annotationVisitor.visitEnd(); annotationVisitor.visitEnd();
} }
@@ -162,7 +167,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
private void generateFieldForObjectInstance() { private void generateFieldForObjectInstance() {
if (isNonLiteralObject()) { if (isNonLiteralObject()) {
Type type = JetTypeMapper.jetImplementationType(descriptor); Type type = JetTypeMapper.jetImplementationType(descriptor);
v.visitField(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "$instance", type.getDescriptor(), null, null); v.newField(myClass, Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "$instance", type.getDescriptor(), null, null);
staticInitializerChunks.add(new CodeChunk() { staticInitializerChunks.add(new CodeChunk() {
@Override @Override
@@ -182,7 +187,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
final JetClassObject classObject = getClassObject(); final JetClassObject classObject = getClassObject();
if (classObject != null) { if (classObject != null) {
Type type = Type.getObjectType(state.getTypeMapper().jvmName(classObject)); Type type = Type.getObjectType(state.getTypeMapper().jvmName(classObject));
v.visitField(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "$classobj", type.getDescriptor(), null, null); v.newField(classObject, Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "$classobj", type.getDescriptor(), null, null);
staticInitializerChunks.add(new CodeChunk() { staticInitializerChunks.add(new CodeChunk() {
@Override @Override
@@ -242,7 +247,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
} }
int flags = Opcodes.ACC_PUBLIC; // TODO int flags = Opcodes.ACC_PUBLIC; // TODO
final MethodVisitor mv = v.visitMethod(flags, "<init>", method.getDescriptor(), null, null); final MethodVisitor mv = v.newMethod(myClass, flags, "<init>", method.getDescriptor(), null, null);
mv.visitCode(); mv.visitCode();
List<ValueParameterDescriptor> paramDescrs = constructorDescriptor != null List<ValueParameterDescriptor> paramDescrs = constructorDescriptor != null
@@ -312,7 +317,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
String delegateField = "$delegate_" + n; String delegateField = "$delegate_" + n;
Type fieldType = JetTypeMapper.jetInterfaceType(superClassDescriptor); Type fieldType = JetTypeMapper.jetInterfaceType(superClassDescriptor);
String fieldDesc = fieldType.getDescriptor(); String fieldDesc = fieldType.getDescriptor();
v.visitField(Opcodes.ACC_PRIVATE, delegateField, fieldDesc, /*TODO*/null, null); v.newField(specifier, Opcodes.ACC_PRIVATE, delegateField, fieldDesc, /*TODO*/null, null);
iv.putfield(classname, delegateField, fieldDesc); iv.putfield(classname, delegateField, fieldDesc);
JetClass superClass = (JetClass) state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, superClassDescriptor); JetClass superClass = (JetClass) state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, superClassDescriptor);
@@ -328,7 +333,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
final Type type = JetTypeMapper.jetImplementationType(outerDescriptor); final Type type = JetTypeMapper.jetImplementationType(outerDescriptor);
String interfaceDesc = type.getDescriptor(); String interfaceDesc = type.getDescriptor();
final String fieldName = "this$0"; final String fieldName = "this$0";
v.visitField(Opcodes.ACC_PRIVATE | Opcodes.ACC_FINAL, fieldName, interfaceDesc, null, null); v.newField(myClass, Opcodes.ACC_PRIVATE | Opcodes.ACC_FINAL, fieldName, interfaceDesc, null, null);
iv.load(0, classType); iv.load(0, classType);
iv.load(frameMap.getOuterThisIndex(), type); iv.load(frameMap.getOuterThisIndex(), type);
iv.putfield(classname, fieldName, interfaceDesc); iv.putfield(classname, fieldName, interfaceDesc);
@@ -393,7 +398,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
Method function = state.getTypeMapper().mapSignature(fun.getName(), fun); Method function = state.getTypeMapper().mapSignature(fun.getName(), fun);
Method functionOriginal = state.getTypeMapper().mapSignature(fun.getName(), fun.getOriginal()); Method functionOriginal = state.getTypeMapper().mapSignature(fun.getName(), fun.getOriginal());
final MethodVisitor mv = v.visitMethod(flags, function.getName(), function.getDescriptor(), null, null); final MethodVisitor mv = v.newMethod(myClass, flags, function.getName(), function.getDescriptor(), null, null);
mv.visitCode(); mv.visitCode();
codegen.generateThisOrOuter(descriptor); codegen.generateThisOrOuter(descriptor);
@@ -475,7 +480,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
else if (declaration instanceof JetEnumEntry && !((JetEnumEntry) declaration).hasPrimaryConstructor()) { else if (declaration instanceof JetEnumEntry && !((JetEnumEntry) declaration).hasPrimaryConstructor()) {
String name = declaration.getName(); String name = declaration.getName();
final String desc = "L" + state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION) + ";"; final String desc = "L" + state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION) + ";";
v.visitField(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL, name, desc, null, null); v.newField(declaration, Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL, name, desc, null, null);
if (myEnumConstants.isEmpty()) { if (myEnumConstants.isEmpty()) {
staticInitializerChunks.add(new CodeChunk() { staticInitializerChunks.add(new CodeChunk() {
@Override @Override
@@ -533,7 +538,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
} }
CallableMethod method = state.getTypeMapper().mapToCallableMethod(constructorDescriptor, kind); CallableMethod method = state.getTypeMapper().mapToCallableMethod(constructorDescriptor, kind);
int flags = Opcodes.ACC_PUBLIC; // TODO int flags = Opcodes.ACC_PUBLIC; // TODO
final MethodVisitor mv = v.visitMethod(flags, "<init>", method.getSignature().getDescriptor(), null, null); final MethodVisitor mv = v.newMethod(constructor, flags, "<init>", method.getSignature().getDescriptor(), null, null);
mv.visitCode(); mv.visitCode();
ConstructorFrameMap frameMap = new ConstructorFrameMap(method, constructorDescriptor, descriptor, kind); ConstructorFrameMap frameMap = new ConstructorFrameMap(method, constructorDescriptor, descriptor, kind);
@@ -677,9 +682,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
if (p.getValOrVarNode() != null) { if (p.getValOrVarNode() != null) {
PropertyDescriptor propertyDescriptor = state.getBindingContext().get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, p); PropertyDescriptor propertyDescriptor = state.getBindingContext().get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, p);
if (propertyDescriptor != null) { if (propertyDescriptor != null) {
propertyCodegen.generateDefaultGetter(propertyDescriptor, Opcodes.ACC_PUBLIC); propertyCodegen.generateDefaultGetter(propertyDescriptor, Opcodes.ACC_PUBLIC, p);
if (propertyDescriptor.isVar()) { if (propertyDescriptor.isVar()) {
propertyCodegen.generateDefaultSetter(propertyDescriptor, Opcodes.ACC_PUBLIC); propertyCodegen.generateDefaultSetter(propertyDescriptor, Opcodes.ACC_PUBLIC, p);
} }
} }
} }
@@ -703,9 +708,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
JetType defaultType = descriptor.getDefaultType(); JetType defaultType = descriptor.getDefaultType();
if(CodegenUtil.hasTypeInfoField(defaultType)) { if(CodegenUtil.hasTypeInfoField(defaultType)) {
if(!CodegenUtil.hasDerivedTypeInfoField(defaultType, true)) { if(!CodegenUtil.hasDerivedTypeInfoField(defaultType, true)) {
v.visitField(Opcodes.ACC_PRIVATE, "$typeInfo", "Ljet/typeinfo/TypeInfo;", null, null); v.newField(myClass, Opcodes.ACC_PRIVATE, "$typeInfo", "Ljet/typeinfo/TypeInfo;", null, null);
MethodVisitor mv = v.visitMethod(Opcodes.ACC_PUBLIC, "getTypeInfo", "()Ljet/typeinfo/TypeInfo;", null, null); MethodVisitor mv = v.newMethod(myClass, Opcodes.ACC_PUBLIC, "getTypeInfo", "()Ljet/typeinfo/TypeInfo;", null, null);
mv.visitCode(); mv.visitCode();
InstructionAdapter iv = new InstructionAdapter(mv); InstructionAdapter iv = new InstructionAdapter(mv);
String owner = state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION); String owner = state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION);
@@ -715,7 +720,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
mv.visitMaxs(0, 0); mv.visitMaxs(0, 0);
mv.visitEnd(); mv.visitEnd();
mv = v.visitMethod(Opcodes.ACC_PROTECTED|Opcodes.ACC_FINAL, "$setTypeInfo", "(Ljet/typeinfo/TypeInfo;)V", null, null); mv = v.newMethod(myClass, Opcodes.ACC_PROTECTED | Opcodes.ACC_FINAL, "$setTypeInfo", "(Ljet/typeinfo/TypeInfo;)V", null, null);
mv.visitCode(); mv.visitCode();
iv = new InstructionAdapter(mv); iv = new InstructionAdapter(mv);
owner = state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION); owner = state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION);
@@ -734,7 +739,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
} }
private void genGetStaticGetTypeInfoMethod() { private void genGetStaticGetTypeInfoMethod() {
final MethodVisitor mv = v.visitMethod(Opcodes.ACC_PUBLIC, "getTypeInfo", "()Ljet/typeinfo/TypeInfo;", null, null); final MethodVisitor mv = v.newMethod(myClass, Opcodes.ACC_PUBLIC, "getTypeInfo", "()Ljet/typeinfo/TypeInfo;", null, null);
mv.visitCode(); mv.visitCode();
InstructionAdapter v = new InstructionAdapter(mv); InstructionAdapter v = new InstructionAdapter(mv);
String owner = state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION); String owner = state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION);
@@ -745,7 +750,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
} }
private void staticTypeInfoField() { private void staticTypeInfoField() {
v.visitField(Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL | Opcodes.ACC_STATIC, "$staticTypeInfo", "Ljet/typeinfo/TypeInfo;", null, null); v.newField(myClass, Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL | Opcodes.ACC_STATIC, "$staticTypeInfo", "Ljet/typeinfo/TypeInfo;", null, null);
staticInitializerChunks.add(new CodeChunk() { staticInitializerChunks.add(new CodeChunk() {
@Override @Override
public void generate(InstructionAdapter v) { public void generate(InstructionAdapter v) {
@@ -776,11 +781,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
String sig = getGetSuperTypesTypeInfoSignature(descriptor.getDefaultType()); String sig = getGetSuperTypesTypeInfoSignature(descriptor.getDefaultType());
final MethodVisitor mv = v.visitMethod(Opcodes.ACC_PUBLIC|Opcodes.ACC_STATIC, final MethodVisitor mv = v.newMethod(myClass, Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC,
"$$getSuperTypesTypeInfo", "$$getSuperTypesTypeInfo",
sig, sig,
null /* TODO */, null /* TODO */,
null); null);
mv.visitCode(); mv.visitCode();
InstructionAdapter v = new InstructionAdapter(mv); InstructionAdapter v = new InstructionAdapter(mv);
@@ -9,10 +9,14 @@ import org.jetbrains.jet.lang.resolve.java.JavaClassDescriptor;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeProjection; import org.jetbrains.jet.lang.types.TypeProjection;
import org.jetbrains.jet.lang.types.TypeUtils; import org.jetbrains.jet.lang.types.TypeUtils;
import org.objectweb.asm.*; import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter; import org.objectweb.asm.commons.InstructionAdapter;
import java.util.*; import java.util.Collections;
import java.util.List;
import java.util.Map;
import static org.objectweb.asm.Opcodes.*; import static org.objectweb.asm.Opcodes.*;
@@ -20,20 +24,20 @@ import static org.objectweb.asm.Opcodes.*;
* @author max * @author max
*/ */
public class NamespaceCodegen { public class NamespaceCodegen {
private final ClassVisitor v; private final ClassBuilder v;
private final GenerationState state; private final GenerationState state;
public NamespaceCodegen(ClassVisitor v, String fqName, GenerationState state, PsiFile sourceFile) { public NamespaceCodegen(ClassBuilder v, String fqName, GenerationState state, PsiFile sourceFile) {
this.v = v; this.v = v;
this.state = state; this.state = state;
v.visit(V1_6, v.defineClass(V1_6,
ACC_PUBLIC, ACC_PUBLIC,
getJVMClassName(fqName), getJVMClassName(fqName),
null, null,
//"jet/lang/Namespace", //"jet/lang/Namespace",
"java/lang/Object", "java/lang/Object",
new String[0] new String[0]
); );
// TODO figure something out for a namespace that spans multiple files // TODO figure something out for a namespace that spans multiple files
v.visitSource(sourceFile.getName(), null); v.visitSource(sourceFile.getName(), null);
@@ -76,8 +80,8 @@ public class NamespaceCodegen {
} }
private void generateStaticInitializers(JetNamespace namespace) { private void generateStaticInitializers(JetNamespace namespace) {
MethodVisitor mv = v.visitMethod(ACC_PUBLIC | ACC_STATIC, MethodVisitor mv = v.newMethod(namespace, ACC_PUBLIC | ACC_STATIC,
"<clinit>", "()V", null, null); "<clinit>", "()V", null, null);
mv.visitCode(); mv.visitCode();
FrameMap frameMap = new FrameMap(); FrameMap frameMap = new FrameMap();
@@ -104,9 +108,9 @@ public class NamespaceCodegen {
String jvmClassName = getJVMClassName(namespace.getName()); String jvmClassName = getJVMClassName(namespace.getName());
for(Map.Entry<JetType,Integer> e : (context.typeInfoConstants != null ? context.typeInfoConstants : Collections.<JetType,Integer>emptyMap()).entrySet()) { for(Map.Entry<JetType,Integer> e : (context.typeInfoConstants != null ? context.typeInfoConstants : Collections.<JetType,Integer>emptyMap()).entrySet()) {
String fieldName = "$typeInfoCache$" + e.getValue(); String fieldName = "$typeInfoCache$" + e.getValue();
v.visitField(ACC_PRIVATE|ACC_STATIC|ACC_SYNTHETIC, fieldName, "Ljet/typeinfo/TypeInfo;", null, null); v.newField(null, ACC_PRIVATE | ACC_STATIC | ACC_SYNTHETIC, fieldName, "Ljet/typeinfo/TypeInfo;", null, null);
MethodVisitor mmv = v.visitMethod(ACC_PUBLIC|ACC_STATIC|ACC_SYNTHETIC, "$getCachedTypeInfo$" + e.getValue(), "()Ljet/typeinfo/TypeInfo;", null, null); MethodVisitor mmv = v.newMethod(null, ACC_PUBLIC | ACC_STATIC | ACC_SYNTHETIC, "$getCachedTypeInfo$" + e.getValue(), "()Ljet/typeinfo/TypeInfo;", null, null);
InstructionAdapter v = new InstructionAdapter(mmv); InstructionAdapter v = new InstructionAdapter(mmv);
v.visitFieldInsn(GETSTATIC, jvmClassName, fieldName, "Ljet/typeinfo/TypeInfo;"); v.visitFieldInsn(GETSTATIC, jvmClassName, fieldName, "Ljet/typeinfo/TypeInfo;");
v.visitInsn(DUP); v.visitInsn(DUP);
@@ -185,7 +189,7 @@ public class NamespaceCodegen {
} }
public void done() { public void done() {
v.visitEnd(); v.done();
} }
public static String getJVMClassName(String fqName) { public static String getJVMClassName(String fqName) {
@@ -2,12 +2,14 @@ package org.jetbrains.jet.codegen;
import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertySetterDescriptor;
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
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.constants.CompileTimeConstant; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.lexer.JetTokens;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes; import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type; import org.objectweb.asm.Type;
@@ -19,10 +21,10 @@ import org.objectweb.asm.commons.InstructionAdapter;
public class PropertyCodegen { public class PropertyCodegen {
private final GenerationState state; private final GenerationState state;
private final FunctionCodegen functionCodegen; private final FunctionCodegen functionCodegen;
private final ClassVisitor v; private final ClassBuilder v;
private final OwnerKind kind; private final OwnerKind kind;
public PropertyCodegen(ClassContext context, ClassVisitor v, FunctionCodegen functionCodegen, GenerationState state) { public PropertyCodegen(ClassContext context, ClassBuilder v, FunctionCodegen functionCodegen, GenerationState state) {
this.v = v; this.v = v;
this.functionCodegen = functionCodegen; this.functionCodegen = functionCodegen;
this.state = state; this.state = state;
@@ -41,9 +43,9 @@ public class PropertyCodegen {
generateSetter(p, propertyDescriptor); generateSetter(p, propertyDescriptor);
} }
else if (kind instanceof OwnerKind.DelegateKind) { else if (kind instanceof OwnerKind.DelegateKind) {
generateDefaultGetter(propertyDescriptor, Opcodes.ACC_PUBLIC); generateDefaultGetter(propertyDescriptor, Opcodes.ACC_PUBLIC, p);
if (propertyDescriptor.isVar()) { if (propertyDescriptor.isVar()) {
generateDefaultSetter(propertyDescriptor, Opcodes.ACC_PUBLIC); generateDefaultSetter(propertyDescriptor, Opcodes.ACC_PUBLIC, p);
} }
} }
} }
@@ -71,7 +73,7 @@ public class PropertyCodegen {
else { else {
modifiers = Opcodes.ACC_PRIVATE; modifiers = Opcodes.ACC_PRIVATE;
} }
v.visitField(modifiers, p.getName(), state.getTypeMapper().mapType(propertyDescriptor.getOutType()).getDescriptor(), null, value); v.newField(p, modifiers, p.getName(), state.getTypeMapper().mapType(propertyDescriptor.getOutType()).getDescriptor(), null, value);
} }
} }
@@ -114,10 +116,10 @@ public class PropertyCodegen {
private void generateDefaultGetter(JetProperty p, JetDeclaration declaration) { private void generateDefaultGetter(JetProperty p, JetDeclaration declaration) {
final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) state.getBindingContext().get(BindingContext.VARIABLE, p); final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) state.getBindingContext().get(BindingContext.VARIABLE, p);
int flags = JetTypeMapper.getAccessModifiers(declaration, Opcodes.ACC_PUBLIC); int flags = JetTypeMapper.getAccessModifiers(declaration, Opcodes.ACC_PUBLIC);
generateDefaultGetter(propertyDescriptor, flags); generateDefaultGetter(propertyDescriptor, flags, p);
} }
public void generateDefaultGetter(PropertyDescriptor propertyDescriptor, int flags) { public void generateDefaultGetter(PropertyDescriptor propertyDescriptor, int flags, PsiElement origin) {
if (kind == OwnerKind.NAMESPACE) { if (kind == OwnerKind.NAMESPACE) {
flags |= Opcodes.ACC_STATIC; flags |= Opcodes.ACC_STATIC;
} }
@@ -129,7 +131,7 @@ public class PropertyCodegen {
final String signature = state.getTypeMapper().mapGetterSignature(propertyDescriptor).getDescriptor(); final String signature = state.getTypeMapper().mapGetterSignature(propertyDescriptor).getDescriptor();
String getterName = getterName(propertyDescriptor.getName()); String getterName = getterName(propertyDescriptor.getName());
MethodVisitor mv = v.visitMethod(flags, getterName, signature, null, null); MethodVisitor mv = v.newMethod(origin, flags, getterName, signature, null, null);
if (!isTrait || kind instanceof OwnerKind.DelegateKind) { if (!isTrait || kind instanceof OwnerKind.DelegateKind) {
mv.visitCode(); mv.visitCode();
InstructionAdapter iv = new InstructionAdapter(mv); InstructionAdapter iv = new InstructionAdapter(mv);
@@ -156,10 +158,10 @@ public class PropertyCodegen {
private void generateDefaultSetter(JetProperty p, JetDeclaration declaration) { private void generateDefaultSetter(JetProperty p, JetDeclaration declaration) {
final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) state.getBindingContext().get(BindingContext.VARIABLE, p); final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) state.getBindingContext().get(BindingContext.VARIABLE, p);
int flags = JetTypeMapper.getAccessModifiers(declaration, Opcodes.ACC_PUBLIC); int flags = JetTypeMapper.getAccessModifiers(declaration, Opcodes.ACC_PUBLIC);
generateDefaultSetter(propertyDescriptor, flags); generateDefaultSetter(propertyDescriptor, flags, p);
} }
public void generateDefaultSetter(PropertyDescriptor propertyDescriptor, int flags) { public void generateDefaultSetter(PropertyDescriptor propertyDescriptor, int flags, PsiElement origin) {
if (kind == OwnerKind.NAMESPACE) { if (kind == OwnerKind.NAMESPACE) {
flags |= Opcodes.ACC_STATIC; flags |= Opcodes.ACC_STATIC;
} }
@@ -170,7 +172,7 @@ public class PropertyCodegen {
flags |= Opcodes.ACC_ABSTRACT; flags |= Opcodes.ACC_ABSTRACT;
final String signature = state.getTypeMapper().mapSetterSignature(propertyDescriptor).getDescriptor(); final String signature = state.getTypeMapper().mapSetterSignature(propertyDescriptor).getDescriptor();
MethodVisitor mv = v.visitMethod(flags, setterName(propertyDescriptor.getName()), signature, null, null); MethodVisitor mv = v.newMethod(origin, flags, setterName(propertyDescriptor.getName()), signature, null, null);
if (!isTrait || kind instanceof OwnerKind.DelegateKind) { if (!isTrait || kind instanceof OwnerKind.DelegateKind) {
mv.visitCode(); mv.visitCode();
InstructionAdapter iv = new InstructionAdapter(mv); InstructionAdapter iv = new InstructionAdapter(mv);
@@ -7,15 +7,12 @@ 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.types.JetStandardClasses; import org.jetbrains.jet.lang.types.JetStandardClasses;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lexer.JetTokens;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Opcodes; import org.objectweb.asm.Opcodes;
import java.util.ArrayList;
import java.util.List; import java.util.List;
public class TraitImplBodyCodegen extends ClassBodyCodegen { public class TraitImplBodyCodegen extends ClassBodyCodegen {
public TraitImplBodyCodegen(JetClassOrObject aClass, ClassContext context, ClassVisitor v, GenerationState state) { public TraitImplBodyCodegen(JetClassOrObject aClass, ClassContext context, ClassBuilder v, GenerationState state) {
super(aClass, context, v, state); super(aClass, context, v, state);
} }
@@ -48,12 +45,12 @@ public class TraitImplBodyCodegen extends ClassBodyCodegen {
@Override @Override
protected void generateDeclaration() { protected void generateDeclaration() {
v.visit(Opcodes.V1_6, v.defineClass(Opcodes.V1_6,
Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL, Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL,
jvmName(), jvmName(),
null, null,
"java/lang/Object", "java/lang/Object",
new String[0] new String[0]
); );
v.visitSource(myClass.getContainingFile().getName(), null); v.visitSource(myClass.getContainingFile().getName(), null);
} }