BothSignatureWriter should write JVM signatures too

(this simplifies body of JetTypeMapper)
This commit is contained in:
Stepan Koltsov
2012-01-13 03:55:10 +04:00
parent 82880c82e3
commit aa2f2742d5
9 changed files with 377 additions and 175 deletions
@@ -3,11 +3,12 @@ package org.jetbrains.jet.codegen;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.resolve.java.JetSignatureUtils;
import org.jetbrains.jet.lang.types.Variance;
import org.jetbrains.jet.rt.signature.JetSignatureAdapter;
import org.jetbrains.jet.rt.signature.JetSignatureReader;
import org.jetbrains.jet.rt.signature.JetSignatureWriter;
import org.jetbrains.jet.lang.types.Variance;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.Method;
import org.objectweb.asm.signature.SignatureVisitor;
import org.objectweb.asm.signature.SignatureWriter;
import org.objectweb.asm.util.CheckSignatureAdapter;
@@ -40,6 +41,7 @@ public class BothSignatureWriter {
TYPE_PARAMETERS,
PARAMETERS,
PARAMETER,
RETURN_TYPE,
METHOD_END,
@@ -55,16 +57,26 @@ public class BothSignatureWriter {
private String kotlinClassParameters;
private String kotlinClassSignature;
private List<String> kotlinParameterTypes = new ArrayList<String>();
private List<JvmMethodParameterSignature> kotlinParameterTypes = new ArrayList<JvmMethodParameterSignature>();
private String kotlinReturnType;
private int jvmCurrentTypeArrayLevel;
private Type jvmCurrentType;
private Type jvmReturnType;
private JvmMethodParameterKind currentParameterKind;
private final Mode mode;
private final boolean needGenerics;
private State state = State.START;
private boolean generic = false;
public BothSignatureWriter(Mode mode) {
public BothSignatureWriter(Mode mode, boolean needGenerics) {
this.mode = mode;
this.needGenerics = needGenerics;
if (DEBUG_SIGNATURE_WRITER) {
signatureVisitor = new CheckSignatureAdapter(mode.asmType, signatureWriter);
} else {
@@ -152,11 +164,27 @@ public class BothSignatureWriter {
}
signatureVisitor().visitBaseType(c);
jetSignatureWriter.visitBaseType(c, nullable);
writeAsmType0(Type.getType(String.valueOf(c)));
}
private String makeArrayPrefix() {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < jvmCurrentTypeArrayLevel; ++i) {
sb.append('[');
}
return sb.toString();
}
private void writeAsmType0(Type type) {
if (jvmCurrentType == null) {
jvmCurrentType = Type.getType(makeArrayPrefix() + type.getDescriptor());
}
}
public void writeClassBegin(String internalName, boolean nullable) {
signatureVisitor().visitClassType(internalName);
jetSignatureWriter.visitClassType(internalName, nullable);
writeAsmType0(Type.getObjectType(internalName));
}
public void writeClassEnd() {
@@ -167,6 +195,9 @@ public class BothSignatureWriter {
public void writeArrayType(boolean nullable) {
push(signatureVisitor().visitArrayType());
jetSignatureWriter.visitArrayType(nullable);
if (jvmCurrentType == null) {
++jvmCurrentTypeArrayLevel;
}
}
public void writeArrayEnd() {
@@ -183,10 +214,11 @@ public class BothSignatureWriter {
pop();
}
public void writeTypeVariable(final String name, boolean nullable) {
public void writeTypeVariable(final String name, boolean nullable, Type asmType) {
signatureVisitor().visitTypeVariable(name);
jetSignatureWriter.visitTypeVariable(name, nullable);
generic = true;
writeAsmType0(asmType);
}
public void writeFormalTypeParameter(final String name, Variance variance) {
@@ -202,7 +234,7 @@ public class BothSignatureWriter {
jetSignatureWriter.visitFormalTypeParameterEnd();
}
public void writerFormalTypeParametersStart() {
public void writeFormalTypeParametersStart() {
checkTopLevel();
transitionState(State.START, State.TYPE_PARAMETERS);
jetSignatureWriter = new JetSignatureWriter();
@@ -242,28 +274,59 @@ public class BothSignatureWriter {
public void writeParametersStart() {
transitionState(State.TYPE_PARAMETERS, State.PARAMETERS);
// hacks
jvmCurrentType = null;
jvmCurrentTypeArrayLevel = 0;
}
public void writeParametersEnd() {
checkState(State.PARAMETERS);
}
public void writeParameterType() {
public void writeParameterType(JvmMethodParameterKind parameterKind) {
transitionState(State.PARAMETERS, State.PARAMETER);
push(signatureVisitor().visitParameterType());
jetSignatureWriter = new JetSignatureWriter();
if (jvmCurrentType != null || jvmCurrentTypeArrayLevel != 0) {
throw new IllegalStateException();
}
if (currentParameterKind != null) {
throw new IllegalStateException();
}
this.currentParameterKind = parameterKind;
//jetSignatureWriter.visitParameterType();
}
public void writeParameterTypeEnd() {
pop();
if (jvmCurrentType == null) {
throw new IllegalStateException();
}
String signature = jetSignatureWriter.toString();
kotlinParameterTypes.add(signature);
kotlinParameterTypes.add(new JvmMethodParameterSignature(jvmCurrentType, signature, currentParameterKind));
if (DEBUG_SIGNATURE_WRITER) {
new JetSignatureReader(signature).acceptTypeOnly(new JetSignatureAdapter());
}
currentParameterKind = null;
jvmCurrentType = null;
jvmCurrentTypeArrayLevel = 0;
jetSignatureWriter = null;
transitionState(State.PARAMETER, State.PARAMETERS);
}
public void writeTypeInfoParameter() {
writeParameterType(JvmMethodParameterKind.TYPE_INFO);
writeAsmType(JetTypeMapper.TYPE_TYPEINFO, false);
writeParameterTypeEnd();
}
public void writeReturnType() {
@@ -271,6 +334,10 @@ public class BothSignatureWriter {
jetSignatureWriter = new JetSignatureWriter();
if (jvmCurrentType != null) {
throw new IllegalStateException();
}
push(signatureVisitor().visitReturnType());
//jetSignatureWriter.visitReturnType();
}
@@ -280,6 +347,14 @@ public class BothSignatureWriter {
kotlinReturnType = jetSignatureWriter.toString();
if (jvmCurrentType == null) {
throw new IllegalStateException();
}
jvmReturnType = jvmCurrentType;
jvmCurrentType = null;
jvmCurrentTypeArrayLevel = 0;
if (DEBUG_SIGNATURE_WRITER) {
new JetSignatureReader(kotlinReturnType).acceptTypeOnly(new JetSignatureAdapter());
}
@@ -288,6 +363,12 @@ public class BothSignatureWriter {
transitionState(State.RETURN_TYPE, State.METHOD_END);
}
public void writeVoidReturn() {
writeReturnType();
writeAsmType(Type.VOID_TYPE, false);
writeReturnTypeEnd();
}
public void writeSupersStart() {
transitionState(State.TYPE_PARAMETERS, State.SUPERS);
jetSignatureWriter = new JetSignatureWriter();
@@ -333,6 +414,14 @@ public class BothSignatureWriter {
@NotNull
public Method makeAsmMethod(String name) {
List<Type> jvmParameterTypes = new ArrayList<Type>(kotlinParameterTypes.size());
for (JvmMethodParameterSignature p : kotlinParameterTypes) {
jvmParameterTypes.add(p.getAsmType());
}
return new Method(name, jvmReturnType, jvmParameterTypes.toArray(new Type[0]));
}
@Nullable
public String makeJavaString() {
@@ -344,7 +433,7 @@ public class BothSignatureWriter {
}
@NotNull
public List<String> makeKotlinParameterTypes() {
public List<JvmMethodParameterSignature> makeKotlinParameterTypes() {
checkState(State.METHOD_END);
// TODO: return nulls if equal to #makeJavaString
return kotlinParameterTypes;
@@ -373,4 +462,19 @@ public class BothSignatureWriter {
return kotlinClassParameters + kotlinClassSignature;
}
@NotNull
public JvmMethodSignature makeJvmMethodSignature(String name) {
if (needGenerics) {
return new JvmMethodSignature(
makeAsmMethod(name),
makeJavaString(),
makeKotlinMethodTypeParameters(),
makeKotlinParameterTypes(),
makeKotlinReturnTypeSignature()
);
} else {
return new JvmMethodSignature(makeAsmMethod(name), makeKotlinParameterTypes());
}
}
}
@@ -19,17 +19,15 @@ public class CallableMethod implements Callable {
private String owner;
private final JvmMethodSignature signature;
private int invokeOpcode;
private final List<Type> valueParameterTypes;
private ClassDescriptor thisClass = null;
private CallableDescriptor receiverFunction = null;
private Type generateCalleeType = null;
public CallableMethod(String owner, JvmMethodSignature signature, int invokeOpcode, List<Type> valueParameterTypes) {
public CallableMethod(String owner, JvmMethodSignature signature, int invokeOpcode) {
this.owner = owner;
this.signature = signature;
this.invokeOpcode = invokeOpcode;
this.valueParameterTypes = valueParameterTypes;
}
public String getOwner() {
@@ -45,7 +43,7 @@ public class CallableMethod implements Callable {
}
public List<Type> getValueParameterTypes() {
return valueParameterTypes;
return signature.getValueParameterTypes();
}
public void setNeedsReceiver(@Nullable CallableDescriptor receiverClass) {
@@ -39,23 +39,40 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
bindingContext = state.getBindingContext();
}
public static Method erasedInvokeSignature(FunctionDescriptor fd) {
public static JvmMethodSignature erasedInvokeSignature(FunctionDescriptor fd) {
BothSignatureWriter signatureWriter = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD, false);
signatureWriter.writeFormalTypeParametersStart();
signatureWriter.writeFormalTypeParametersEnd();
boolean isExtensionFunction = fd.getReceiverParameter().exists();
int paramCount = fd.getValueParameters().size();
if (isExtensionFunction) {
paramCount++;
}
signatureWriter.writeParametersStart();
for (int i = 0; i < paramCount; ++i) {
signatureWriter.writeParameterType(JvmMethodParameterKind.VALUE);
signatureWriter.writeAsmType(JetTypeMapper.TYPE_OBJECT, true);
signatureWriter.writeParameterTypeEnd();
}
signatureWriter.writeParametersEnd();
Type[] args = new Type[paramCount];
Arrays.fill(args, JetTypeMapper.TYPE_OBJECT);
return new Method("invoke", JetTypeMapper.TYPE_OBJECT, args);
signatureWriter.writeReturnType();
signatureWriter.writeAsmType(JetTypeMapper.TYPE_OBJECT, true);
signatureWriter.writeReturnTypeEnd();
return signatureWriter.makeJvmMethodSignature("invoke");
}
public static CallableMethod asCallableMethod(FunctionDescriptor fd) {
Method descriptor = erasedInvokeSignature(fd);
JvmMethodSignature descriptor = erasedInvokeSignature(fd);
String owner = getInternalClassName(fd);
JvmMethodSignature jvmMethodSignature = new JvmMethodSignature(descriptor, null, null, null, "");
final CallableMethod result = new CallableMethod(owner, jvmMethodSignature, INVOKEVIRTUAL, Arrays.asList(descriptor.getArgumentTypes()));
final CallableMethod result = new CallableMethod(owner, descriptor, INVOKEVIRTUAL);
if (fd.getReceiverParameter().exists()) {
result.setNeedsReceiver(fd);
}
@@ -63,8 +80,8 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
return result;
}
public Method invokeSignature(FunctionDescriptor fd) {
return state.getTypeMapper().mapSignature("invoke", fd).getAsmMethod();
public JvmMethodSignature invokeSignature(FunctionDescriptor fd) {
return state.getTypeMapper().mapSignature("invoke", fd);
}
public GeneratedAnonymousClassDescriptor gen(JetFunctionLiteralExpression fun) {
@@ -166,19 +183,19 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
final CodegenContext.ClosureContext closureContext = context.intoClosure(funDescriptor, function, name, this, state.getTypeMapper());
FunctionCodegen fc = new FunctionCodegen(closureContext, cv, state);
JvmMethodSignature jvmMethodSignature = new JvmMethodSignature(invokeSignature(funDescriptor), null, null, null, "");
JvmMethodSignature jvmMethodSignature = invokeSignature(funDescriptor);
fc.generateMethod(body, jvmMethodSignature, null, funDescriptor);
return closureContext.outerWasUsed;
}
private void generateBridge(String className, FunctionDescriptor funDescriptor, JetExpression fun, ClassBuilder cv) {
final Method bridge = erasedInvokeSignature(funDescriptor);
final Method delegate = invokeSignature(funDescriptor);
final JvmMethodSignature bridge = erasedInvokeSignature(funDescriptor);
final Method delegate = invokeSignature(funDescriptor).getAsmMethod();
if(bridge.getDescriptor().equals(delegate.getDescriptor()))
if(bridge.getAsmMethod().getDescriptor().equals(delegate.getDescriptor()))
return;
final MethodVisitor mv = cv.newMethod(fun, ACC_PUBLIC, "invoke", bridge.getDescriptor(), null, new String[0]);
final MethodVisitor mv = cv.newMethod(fun, ACC_PUBLIC, "invoke", bridge.getAsmMethod().getDescriptor(), null, new String[0]);
if (cv.generateCode()) {
mv.visitCode();
@@ -1,6 +1,7 @@
package org.jetbrains.jet.codegen;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*;
@@ -144,7 +145,7 @@ public class FunctionCodegen {
av.visit(JvmStdlibNames.JET_VALUE_PARAMETER_NULLABLE_FIELD, true);
}
if (jvmSignature.getKotlinParameterTypes() != null && jvmSignature.getKotlinParameterTypes().get(i) != null) {
av.visit(JvmStdlibNames.JET_VALUE_PARAMETER_TYPE_FIELD, jvmSignature.getKotlinParameterTypes().get(i + start));
av.visit(JvmStdlibNames.JET_VALUE_PARAMETER_TYPE_FIELD, jvmSignature.getKotlinParameterTypes().get(i + start).getKotlinSignature());
}
av.visitEnd();
}
@@ -115,7 +115,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
LinkedHashSet<String> superInterfacesLinkedHashSet = new LinkedHashSet<String>();
BothSignatureWriter signatureVisitor = new BothSignatureWriter(BothSignatureWriter.Mode.CLASS);
// TODO: generics signature is not always needed
BothSignatureWriter signatureVisitor = new BothSignatureWriter(BothSignatureWriter.Mode.CLASS, true);
{ // type parameters
@@ -351,17 +352,31 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
Method constructorMethod;
CallableMethod callableMethod;
if (constructorDescriptor == null) {
List<Type> parameterTypes = new ArrayList<Type>();
BothSignatureWriter signatureWriter = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD, false);
signatureWriter.writeFormalTypeParametersStart();
signatureWriter.writeFormalTypeParametersEnd();
signatureWriter.writeParametersStart();
if (CodegenUtil.hasThis0(descriptor)) {
parameterTypes.add(typeMapper.mapType(CodegenUtil.getOuterClassDescriptor(descriptor).getDefaultType(), OwnerKind.IMPLEMENTATION));
signatureWriter.writeParameterType(JvmMethodParameterKind.THIS0);
typeMapper.mapType(CodegenUtil.getOuterClassDescriptor(descriptor).getDefaultType(), OwnerKind.IMPLEMENTATION, signatureWriter, false);
signatureWriter.writeParameterTypeEnd();
}
if (CodegenUtil.requireTypeInfoConstructorArg(descriptor.getDefaultType())) {
parameterTypes.add(JetTypeMapper.TYPE_TYPEINFO);
signatureWriter.writeTypeInfoParameter();
}
constructorMethod = new Method("<init>", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()]));
callableMethod = new CallableMethod("", new JvmMethodSignature(constructorMethod, null, null, null, "") /* TODO */, Opcodes.INVOKESPECIAL, Collections.<Type>emptyList());
signatureWriter.writeParametersEnd();
signatureWriter.writeVoidReturn();
JvmMethodSignature jvmMethodSignature = signatureWriter.makeJvmMethodSignature("<init>");
constructorMethod = jvmMethodSignature.getAsmMethod();
callableMethod = new CallableMethod("", jvmMethodSignature, Opcodes.INVOKESPECIAL);
}
else {
callableMethod = typeMapper.mapToCallableMethod(constructorDescriptor, kind);
@@ -306,12 +306,13 @@ public class JetTypeMapper {
}
if (descriptor instanceof TypeParameterDescriptor) {
Type type = mapType(((TypeParameterDescriptor) descriptor).getUpperBoundsAsType(), kind);
if (signatureVisitor != null) {
TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) jetType.getConstructor().getDeclarationDescriptor();
signatureVisitor.writeTypeVariable(typeParameterDescriptor.getName(), jetType.isNullable());
signatureVisitor.writeTypeVariable(typeParameterDescriptor.getName(), jetType.isNullable(), type);
}
return mapType(((TypeParameterDescriptor) descriptor).getUpperBoundsAsType(), kind);
return type;
}
throw new UnsupportedOperationException("Unknown type " + jetType);
@@ -355,8 +356,7 @@ public class JetTypeMapper {
return null;
final DeclarationDescriptor functionParent = functionDescriptor.getContainingDeclaration();
final List<Type> valueParameterTypes = new ArrayList<Type>();
JvmMethodSignature descriptor = mapSignature(functionDescriptor.getOriginal(), true, valueParameterTypes, kind);
JvmMethodSignature descriptor = mapSignature(functionDescriptor.getOriginal(), true, kind);
String owner;
int invokeOpcode;
ClassDescriptor thisClass;
@@ -383,7 +383,7 @@ public class JetTypeMapper {
? (superCall ? Opcodes.INVOKESTATIC : Opcodes.INVOKEINTERFACE)
: (superCall ? Opcodes.INVOKESPECIAL : Opcodes.INVOKEVIRTUAL);
if(isInterface && superCall) {
descriptor = mapSignature(functionDescriptor.getOriginal(), false, valueParameterTypes, OwnerKind.TRAIT_IMPL);
descriptor = mapSignature(functionDescriptor.getOriginal(), false, OwnerKind.TRAIT_IMPL);
}
thisClass = (ClassDescriptor) functionParent;
}
@@ -391,7 +391,7 @@ public class JetTypeMapper {
throw new UnsupportedOperationException("unknown function parent");
}
final CallableMethod result = new CallableMethod(owner, descriptor, invokeOpcode, valueParameterTypes);
final CallableMethod result = new CallableMethod(owner, descriptor, invokeOpcode);
result.setNeedsThis(thisClass);
if(functionDescriptor.getReceiverParameter().exists()) {
result.setNeedsReceiver(functionDescriptor);
@@ -400,7 +400,7 @@ public class JetTypeMapper {
return result;
}
private JvmMethodSignature mapSignature(FunctionDescriptor f, boolean needGenericSignature, List<Type> valueParameterTypes, OwnerKind kind) {
private JvmMethodSignature mapSignature(FunctionDescriptor f, boolean needGenericSignature, OwnerKind kind) {
for (ValueParameterDescriptor valueParameterDescriptor : f.getValueParameters()) {
if (valueParameterDescriptor.hasDefaultValue()) {
@@ -413,94 +413,57 @@ public class JetTypeMapper {
needGenericSignature = false;
}
BothSignatureWriter signatureVisitor = null;
if (needGenericSignature) {
signatureVisitor = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD);
}
BothSignatureWriter signatureVisitor = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD, needGenericSignature);
writeFormalTypeParameters(f.getTypeParameters(), signatureVisitor);
final ReceiverDescriptor receiverTypeRef = f.getReceiverParameter();
final JetType receiverType = !receiverTypeRef.exists() ? null : receiverTypeRef.getType();
final List<ValueParameterDescriptor> parameters = f.getValueParameters();
List<Type> parameterTypes = new ArrayList<Type>();
signatureVisitor.writeParametersStart();
if(kind == OwnerKind.TRAIT_IMPL) {
ClassDescriptor containingDeclaration = (ClassDescriptor) f.getContainingDeclaration();
JetType jetType = TraitImplBodyCodegen.getSuperClass(containingDeclaration, bindingContext);
Type type = mapType(jetType, signatureVisitor);
Type type = mapType(jetType);
if(type.getInternalName().equals("java/lang/Object")) {
jetType = containingDeclaration.getDefaultType();
type = mapType(jetType, signatureVisitor);
type = mapType(jetType);
}
valueParameterTypes.add(type);
parameterTypes.add(type);
signatureVisitor.writeParameterType(JvmMethodParameterKind.THIS);
signatureVisitor.writeAsmType(type, jetType.isNullable());
signatureVisitor.writeParameterTypeEnd();
}
if (receiverType != null) {
if (signatureVisitor != null) {
signatureVisitor.writeParameterType();
}
parameterTypes.add(mapType(receiverType, signatureVisitor));
if (signatureVisitor != null) {
signatureVisitor.writeParameterTypeEnd();
}
}
if (signatureVisitor != null) {
signatureVisitor.writeParametersStart();
signatureVisitor.writeParameterType(JvmMethodParameterKind.RECEIVER);
mapType(receiverType, signatureVisitor);
signatureVisitor.writeParameterTypeEnd();
}
for (TypeParameterDescriptor parameterDescriptor : f.getTypeParameters()) {
if(parameterDescriptor.isReified()) {
parameterTypes.add(TYPE_TYPEINFO);
if (signatureVisitor != null) {
signatureVisitor.writeParameterType();
visitAsmType(signatureVisitor, TYPE_TYPEINFO, false);
signatureVisitor.writeParameterTypeEnd();
}
signatureVisitor.writeTypeInfoParameter();
}
}
for (ValueParameterDescriptor parameter : parameters) {
if (signatureVisitor != null) {
signatureVisitor.writeParameterType();
}
Type type = mapType(parameter.getOutType(), signatureVisitor);
if (signatureVisitor != null) {
signatureVisitor.writeParameterTypeEnd();
}
valueParameterTypes.add(type);
parameterTypes.add(type);
signatureVisitor.writeParameterType(JvmMethodParameterKind.VALUE);
mapType(parameter.getOutType(), signatureVisitor);
signatureVisitor.writeParameterTypeEnd();
}
if (signatureVisitor != null) {
signatureVisitor.writeParametersEnd();
}
Type returnType;
signatureVisitor.writeParametersEnd();
if (f instanceof ConstructorDescriptor) {
returnType = Type.VOID_TYPE;
if (signatureVisitor != null) {
signatureVisitor.writeReturnType();
visitAsmType(signatureVisitor, Type.VOID_TYPE, false);
signatureVisitor.writeReturnTypeEnd();
}
signatureVisitor.writeVoidReturn();
} else {
if (signatureVisitor != null) {
signatureVisitor.writeReturnType();
returnType = mapReturnType(f.getReturnType(), signatureVisitor);
signatureVisitor.writeReturnTypeEnd();
}
else {
returnType = mapReturnType(f.getReturnType(), null);
}
}
Method method = new Method(f.getName(), returnType, parameterTypes.toArray(new Type[parameterTypes.size()]));
if (signatureVisitor == null) {
return new JvmMethodSignature(method, null, null, null, "");
} else {
return new JvmMethodSignature(method, signatureVisitor.makeJavaString(),
signatureVisitor.makeKotlinMethodTypeParameters(),
signatureVisitor.makeKotlinParameterTypes(),
signatureVisitor.makeKotlinReturnTypeSignature());
signatureVisitor.writeReturnType();
mapReturnType(f.getReturnType(), signatureVisitor);
signatureVisitor.writeReturnTypeEnd();
}
return signatureVisitor.makeJvmMethodSignature(f.getName());
}
@@ -509,7 +472,7 @@ public class JetTypeMapper {
return;
}
signatureVisitor.writerFormalTypeParametersStart();
signatureVisitor.writeFormalTypeParametersStart();
for (TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
writeFormalTypeParameter(typeParameterDescriptor, signatureVisitor);
}
@@ -560,27 +523,43 @@ public class JetTypeMapper {
public JvmMethodSignature mapSignature(String name, FunctionDescriptor f) {
final ReceiverDescriptor receiver = f.getReceiverParameter();
BothSignatureWriter signatureWriter = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD, false);
signatureWriter.writeFormalTypeParametersStart();
signatureWriter.writeFormalTypeParametersEnd();
signatureWriter.writeParametersStart();
final List<ValueParameterDescriptor> parameters = f.getValueParameters();
List<Type> parameterTypes = new ArrayList<Type>();
if (receiver.exists()) {
parameterTypes.add(mapType(receiver.getType()));
signatureWriter.writeParameterType(JvmMethodParameterKind.RECEIVER);
mapType(receiver.getType(), signatureWriter);
signatureWriter.writeParameterTypeEnd();
}
for (ValueParameterDescriptor parameter : parameters) {
parameterTypes.add(mapType(parameter.getOutType()));
signatureWriter.writeParameterType(JvmMethodParameterKind.VALUE);
mapType(parameter.getOutType(), signatureWriter);
signatureWriter.writeParameterTypeEnd();
}
Type returnType = mapReturnType(f.getReturnType());
// TODO: proper generic signature
return new JvmMethodSignature(new Method(name, returnType, parameterTypes.toArray(new Type[parameterTypes.size()])), null, null, null, "");
signatureWriter.writeParametersEnd();
signatureWriter.writeReturnType();
mapReturnType(f.getReturnType(), signatureWriter);
signatureWriter.writeReturnTypeEnd();
return signatureWriter.makeJvmMethodSignature(name);
}
public JvmPropertyAccessorSignature mapGetterSignature(PropertyDescriptor descriptor, OwnerKind kind) {
String name = PropertyCodegen.getterName(descriptor.getName());
ArrayList<Type> params = new ArrayList<Type>();
BothSignatureWriter signatureWriter = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD);
// TODO: do not generate generics if not needed
BothSignatureWriter signatureWriter = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD, true);
signatureWriter.writerFormalTypeParametersStart();
signatureWriter.writeFormalTypeParametersStart();
signatureWriter.writeFormalTypeParametersEnd();
signatureWriter.writeParametersStart();
@@ -588,41 +567,30 @@ public class JetTypeMapper {
if(kind == OwnerKind.TRAIT_IMPL) {
ClassDescriptor containingDeclaration = (ClassDescriptor) descriptor.getContainingDeclaration();
assert containingDeclaration != null;
signatureWriter.writeParameterType();
params.add(mapType(containingDeclaration.getDefaultType(), signatureWriter));
signatureWriter.writeParameterType(JvmMethodParameterKind.THIS);
mapType(containingDeclaration.getDefaultType(), signatureWriter);
signatureWriter.writeParameterTypeEnd();
}
if(descriptor.getReceiverParameter().exists()) {
signatureWriter.writeParameterType();
params.add(mapType(descriptor.getReceiverParameter().getType(), signatureWriter));
signatureWriter.writeParameterType(JvmMethodParameterKind.RECEIVER);
mapType(descriptor.getReceiverParameter().getType(), signatureWriter);
signatureWriter.writeParameterTypeEnd();
}
for (TypeParameterDescriptor typeParameterDescriptor : descriptor.getTypeParameters()) {
if(typeParameterDescriptor.isReified()) {
signatureWriter.writeParameterType();
params.add(TYPE_TYPEINFO);
visitAsmType(signatureWriter, TYPE_TYPEINFO, false);
signatureWriter.writeParameterTypeEnd();
signatureWriter.writeTypeInfoParameter();
}
}
signatureWriter.writeParametersEnd();
signatureWriter.writeReturnType();
Type returnType = mapType(descriptor.getOutType(), signatureWriter);
mapType(descriptor.getOutType(), signatureWriter);
signatureWriter.writeReturnTypeEnd();
// TODO: proper generic signature
Method asmMethod = new Method(name, returnType, params.toArray(new Type[params.size()]));
JvmMethodSignature jvmMethodSignature = new JvmMethodSignature(
asmMethod,
signatureWriter.makeJavaString(),
signatureWriter.makeKotlinMethodTypeParameters(),
signatureWriter.makeKotlinParameterTypes(),
signatureWriter.makeKotlinReturnTypeSignature()
);
JvmMethodSignature jvmMethodSignature = signatureWriter.makeJvmMethodSignature(name);
return new JvmPropertyAccessorSignature(jvmMethodSignature, jvmMethodSignature.getKotlinReturnType());
}
@@ -632,10 +600,11 @@ public class JetTypeMapper {
if (!descriptor.isVar()) {
return null;
}
// TODO: generics signature is not always needed
BothSignatureWriter signatureWriter = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD, true);
BothSignatureWriter signatureWriter = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD);
signatureWriter.writerFormalTypeParametersStart();
signatureWriter.writeFormalTypeParametersStart();
signatureWriter.writeFormalTypeParametersEnd();
JetType outType = descriptor.getOutType();
@@ -643,79 +612,77 @@ public class JetTypeMapper {
signatureWriter.writeParametersStart();
String name = PropertyCodegen.setterName(descriptor.getName());
ArrayList<Type> params = new ArrayList<Type>();
if(kind == OwnerKind.TRAIT_IMPL) {
ClassDescriptor containingDeclaration = (ClassDescriptor) descriptor.getContainingDeclaration();
assert containingDeclaration != null;
signatureWriter.writeParameterType();
params.add(mapType(containingDeclaration.getDefaultType(), signatureWriter));
signatureWriter.writeParameterType(JvmMethodParameterKind.THIS);
mapType(containingDeclaration.getDefaultType(), signatureWriter);
signatureWriter.writeParameterTypeEnd();
}
if(descriptor.getReceiverParameter().exists()) {
signatureWriter.writeParameterType();
params.add(mapType(descriptor.getReceiverParameter().getType(), signatureWriter));
signatureWriter.writeParameterType(JvmMethodParameterKind.RECEIVER);
mapType(descriptor.getReceiverParameter().getType(), signatureWriter);
signatureWriter.writeParameterTypeEnd();
}
for (TypeParameterDescriptor typeParameterDescriptor : descriptor.getTypeParameters()) {
if(typeParameterDescriptor.isReified()) {
signatureWriter.writeParameterType();
params.add(TYPE_TYPEINFO);
signatureWriter.writeParameterType();
visitAsmType(signatureWriter, TYPE_TYPEINFO, false);
signatureWriter.writeParameterTypeEnd();
signatureWriter.writeTypeInfoParameter();
}
}
signatureWriter.writeParameterType();
params.add(mapType(outType, signatureWriter));
signatureWriter.writeParameterType(JvmMethodParameterKind.VALUE);
mapType(outType, signatureWriter);
signatureWriter.writeParameterTypeEnd();
signatureWriter.writeParametersEnd();
signatureWriter.writeReturnType();
visitAsmType(signatureWriter, Type.VOID_TYPE, false);
signatureWriter.writeReturnTypeEnd();
signatureWriter.writeVoidReturn();
Method asmMethod = new Method(name, Type.VOID_TYPE, params.toArray(new Type[params.size()]));
JvmMethodSignature jvmMethodSignature = new JvmMethodSignature(
asmMethod,
signatureWriter.makeJavaString(),
signatureWriter.makeKotlinMethodTypeParameters(),
signatureWriter.makeKotlinParameterTypes(),
signatureWriter.makeKotlinReturnTypeSignature()
);
JvmMethodSignature jvmMethodSignature = signatureWriter.makeJvmMethodSignature(name);
return new JvmPropertyAccessorSignature(jvmMethodSignature, jvmMethodSignature.getKotlinParameterType(jvmMethodSignature.getParameterCount() - 1));
}
private JvmMethodSignature mapConstructorSignature(ConstructorDescriptor descriptor, List<Type> valueParameterTypes) {
private JvmMethodSignature mapConstructorSignature(ConstructorDescriptor descriptor) {
BothSignatureWriter signatureWriter = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD, true);
List<ValueParameterDescriptor> parameters = descriptor.getOriginal().getValueParameters();
List<Type> parameterTypes = new ArrayList<Type>();
ClassDescriptor classDescriptor = descriptor.getContainingDeclaration();
signatureWriter.writeFormalTypeParametersStart();
signatureWriter.writeFormalTypeParametersEnd();
signatureWriter.writeParametersStart();
if (CodegenUtil.hasThis0(classDescriptor)) {
parameterTypes.add(mapType(CodegenUtil.getOuterClassDescriptor(classDescriptor).getDefaultType(), OwnerKind.IMPLEMENTATION));
signatureWriter.writeParameterType(JvmMethodParameterKind.THIS0);
mapType(CodegenUtil.getOuterClassDescriptor(classDescriptor).getDefaultType(), OwnerKind.IMPLEMENTATION, signatureWriter);
signatureWriter.writeParameterTypeEnd();
}
if (CodegenUtil.requireTypeInfoConstructorArg(classDescriptor.getDefaultType())) {
parameterTypes.add(TYPE_TYPEINFO);
signatureWriter.writeTypeInfoParameter();
}
for (ValueParameterDescriptor parameter : parameters) {
final Type type = mapType(parameter.getOutType());
parameterTypes.add(type);
valueParameterTypes.add(type);
signatureWriter.writeParameterType(JvmMethodParameterKind.VALUE);
mapType(parameter.getOutType(), signatureWriter);
signatureWriter.writeParameterTypeEnd();
}
signatureWriter.writeParametersEnd();
signatureWriter.writeVoidReturn();
Method method = new Method("<init>", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()]));
return new JvmMethodSignature(method, null, null, null, ""); // TODO: generics signature
return signatureWriter.makeJvmMethodSignature("<init>");
}
public CallableMethod mapToCallableMethod(ConstructorDescriptor descriptor, OwnerKind kind) {
List<Type> valueParameterTypes = new ArrayList<Type>();
final JvmMethodSignature method = mapConstructorSignature(descriptor, valueParameterTypes);
final JvmMethodSignature method = mapConstructorSignature(descriptor);
String owner = mapType(descriptor.getContainingDeclaration().getDefaultType(), kind).getInternalName();
return new CallableMethod(owner, method, INVOKESPECIAL, valueParameterTypes);
return new CallableMethod(owner, method, INVOKESPECIAL);
}
static int getAccessModifiers(JetDeclaration p, int defaultFlags) {
@@ -0,0 +1,15 @@
package org.jetbrains.jet.codegen;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
/**
* @author Stepan Koltsov
*/
public enum JvmMethodParameterKind {
VALUE,
THIS,
/** @see CodegenUtil#hasThis0(ClassDescriptor) */
THIS0,
RECEIVER,
TYPE_INFO,
}
@@ -0,0 +1,38 @@
package org.jetbrains.jet.codegen;
import org.jetbrains.annotations.NotNull;
import org.objectweb.asm.Type;
/**
* @author Stepan Koltsov
*/
public class JvmMethodParameterSignature {
@NotNull
private final Type asmType;
@NotNull
private final String kotlinSignature;
@NotNull
private final JvmMethodParameterKind kind;
public JvmMethodParameterSignature(
@NotNull Type asmType, @NotNull String kotlinSignature, @NotNull JvmMethodParameterKind kind) {
this.asmType = asmType;
this.kotlinSignature = kotlinSignature;
this.kind = kind;
}
@NotNull
public Type getAsmType() {
return asmType;
}
@NotNull
public String getKotlinSignature() {
return kotlinSignature;
}
@NotNull
public JvmMethodParameterKind getKind() {
return kind;
}
}
@@ -2,46 +2,76 @@ package org.jetbrains.jet.codegen;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.Method;
import java.util.ArrayList;
import java.util.List;
/**
* @author Stepan Koltsov
*/
public class JvmMethodSignature {
@NotNull
private final Method asmMethod;
/** Null when we don't care about type parameters */
private final String genericsSignature;
private final String kotlinTypeParameter;
private final List<String> kotlinParameterTypes;
@NotNull
private final List<JvmMethodParameterSignature> kotlinParameterTypes;
@NotNull
private final String kotlinReturnType;
/**
* Generics info is generated. However it can be trivial (e.g. fields are null).
*/
private final boolean genericsAvailable;
public JvmMethodSignature(@NotNull Method asmMethod, @Nullable String genericsSignature,
@Nullable String kotlinTypeParameters, @Nullable List<String> kotlinParameterTypes, @NotNull String kotlinReturnType) {
@Nullable String kotlinTypeParameters, @NotNull List<JvmMethodParameterSignature> kotlinParameterTypes, @NotNull String kotlinReturnType) {
this.asmMethod = asmMethod;
this.genericsSignature = genericsSignature;
this.kotlinTypeParameter = kotlinTypeParameters;
this.kotlinParameterTypes = kotlinParameterTypes;
this.kotlinReturnType = kotlinReturnType;
this.genericsAvailable = true;
}
public JvmMethodSignature(@NotNull Method asmMethod, @NotNull List<JvmMethodParameterSignature> kotlinParameterTypes) {
this.asmMethod = asmMethod;
this.genericsSignature = null;
this.kotlinTypeParameter = null;
this.kotlinParameterTypes = kotlinParameterTypes;
this.kotlinReturnType = "";
this.genericsAvailable = false;
}
private void checkGenericsAvailable() {
if (!genericsAvailable) {
// TODO: uncomment following line and fix all broken tests
//throw new IllegalStateException("incorrect call sequence");
}
}
@NotNull
public Method getAsmMethod() {
return asmMethod;
}
public String getGenericsSignature() {
checkGenericsAvailable();
return genericsSignature;
}
public String getKotlinTypeParameter() {
checkGenericsAvailable();
return kotlinTypeParameter;
}
@Nullable
public List<String> getKotlinParameterTypes() {
public List<JvmMethodParameterSignature> getKotlinParameterTypes() {
checkGenericsAvailable();
return kotlinParameterTypes;
}
@@ -52,15 +82,32 @@ public class JvmMethodSignature {
@NotNull
public String getKotlinParameterType(int i) {
checkGenericsAvailable();
if (kotlinParameterTypes == null) {
return "";
} else {
return kotlinParameterTypes.get(i);
return kotlinParameterTypes.get(i).getKotlinSignature();
}
}
@NotNull
public String getKotlinReturnType() {
checkGenericsAvailable();
return kotlinReturnType;
}
public List<Type> getValueParameterTypes() {
List<Type> r = new ArrayList<Type>(kotlinParameterTypes.size());
for (JvmMethodParameterSignature p : kotlinParameterTypes) {
if (p.getKind() == JvmMethodParameterKind.VALUE) {
r.add(p.getAsmType());
}
}
return r;
}
@NotNull
public String getName() {
return asmMethod.getName();
}
}