writing java method signatures

All tests pass, but it does not mean nothing is broken.
This commit is contained in:
Stepan Koltsov
2011-12-08 04:31:44 +04:00
parent ec83517f8d
commit 0656f1f0e0
33 changed files with 339 additions and 80 deletions
@@ -19,7 +19,7 @@ import java.util.List;
*/
public class CallableMethod implements Callable {
private String owner;
private final Method signature;
private final JvmMethodSignature signature;
private int invokeOpcode;
private final List<Type> valueParameterTypes;
private ClassDescriptor thisClass = null;
@@ -27,7 +27,7 @@ public class CallableMethod implements Callable {
private CallableDescriptor receiverFunction = null;
private Type generateCalleeType = null;
public CallableMethod(String owner, Method signature, int invokeOpcode, List<Type> valueParameterTypes) {
public CallableMethod(String owner, JvmMethodSignature signature, int invokeOpcode, List<Type> valueParameterTypes) {
this.owner = owner;
this.signature = signature;
this.invokeOpcode = invokeOpcode;
@@ -38,7 +38,7 @@ public class CallableMethod implements Callable {
return owner;
}
public Method getSignature() {
public JvmMethodSignature getSignature() {
return signature;
}
@@ -67,7 +67,7 @@ public class CallableMethod implements Callable {
}
void invoke(InstructionAdapter v) {
v.visitMethodInsn(getInvokeOpcode(), getOwner(), getSignature().getName(), getSignature().getDescriptor());
v.visitMethodInsn(getInvokeOpcode(), getOwner(), getSignature().getAsmMethod().getName(), getSignature().getAsmMethod().getDescriptor());
}
public void requestGenerateCallee(Type objectType) {
@@ -80,14 +80,14 @@ public class CallableMethod implements Callable {
public void invokeWithDefault(InstructionAdapter v, int mask) {
v.iconst(mask);
String desc = getSignature().getDescriptor().replace(")", "I)");
if("<init>".equals(getSignature().getName())) {
String desc = getSignature().getAsmMethod().getDescriptor().replace(")", "I)");
if("<init>".equals(getSignature().getAsmMethod().getName())) {
v.visitMethodInsn(Opcodes.INVOKESPECIAL, getOwner(), "<init>", desc);
}
else {
if(getInvokeOpcode() != Opcodes.INVOKESTATIC)
desc = desc.replace("(", "(L" + getOwner() + ";");
v.visitMethodInsn(Opcodes.INVOKESTATIC, getInvokeOpcode() == Opcodes.INVOKEINTERFACE ? getOwner() + "$$TImpl" : getOwner(), getSignature().getName() + "$default", desc);
v.visitMethodInsn(Opcodes.INVOKESTATIC, getInvokeOpcode() == Opcodes.INVOKEINTERFACE ? getOwner() + "$$TImpl" : getOwner(), getSignature().getAsmMethod().getName() + "$default", desc);
}
}
@@ -53,7 +53,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
public static CallableMethod asCallableMethod(FunctionDescriptor fd) {
Method descriptor = erasedInvokeSignature(fd);
String owner = getInternalClassName(fd);
final CallableMethod result = new CallableMethod(owner, descriptor, INVOKEVIRTUAL, Arrays.asList(descriptor.getArgumentTypes()));
final CallableMethod result = new CallableMethod(owner, new JvmMethodSignature(descriptor, null), INVOKEVIRTUAL, Arrays.asList(descriptor.getArgumentTypes()));
if (fd.getReceiverParameter().exists()) {
result.setNeedsReceiver(fd);
}
@@ -62,7 +62,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
}
public Method invokeSignature(FunctionDescriptor fd) {
return state.getTypeMapper().mapSignature("invoke", fd);
return state.getTypeMapper().mapSignature("invoke", fd).getAsmMethod();
}
public GeneratedAnonymousClassDescriptor gen(JetFunctionLiteralExpression fun) {
@@ -165,7 +165,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
final CodegenContext.ClosureContext closureContext = context.intoClosure(funDescriptor, function, name, this, state.getTypeMapper());
FunctionCodegen fc = new FunctionCodegen(closureContext, cv, state);
fc.generateMethod(body, invokeSignature(funDescriptor), funDescriptor);
fc.generateMethod(body, new JvmMethodSignature(invokeSignature(funDescriptor), null), funDescriptor);
return closureContext.outerWasUsed;
}
@@ -991,7 +991,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
}
}
v.visitMethodInsn(isStatic ? Opcodes.INVOKESTATIC : isInterface ? Opcodes.INVOKEINTERFACE : Opcodes.INVOKEVIRTUAL, owner, functionDescriptor.getName(), typeMapper.mapSignature(functionDescriptor.getName(),functionDescriptor).getDescriptor());
v.visitMethodInsn(isStatic ? Opcodes.INVOKESTATIC : isInterface ? Opcodes.INVOKEINTERFACE : Opcodes.INVOKEVIRTUAL, owner, functionDescriptor.getName(), typeMapper.mapSignature(functionDescriptor.getName(),functionDescriptor).getAsmMethod().getDescriptor());
StackValue.onStack(asmType(functionDescriptor.getReturnType())).coerce(type, v);
}
@@ -1034,7 +1034,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
}
}
if(!(containingDeclaration instanceof JavaNamespaceDescriptor) && !(containingDeclaration instanceof JavaClassDescriptor))
getter = typeMapper.mapGetterSignature(propertyDescriptor, OwnerKind.IMPLEMENTATION);
getter = typeMapper.mapGetterSignature(propertyDescriptor, OwnerKind.IMPLEMENTATION).getAsmMethod();
else
getter = null;
}
@@ -1043,10 +1043,12 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
setter = null;
}
else {
if(!(containingDeclaration instanceof JavaNamespaceDescriptor) && !(containingDeclaration instanceof JavaClassDescriptor))
setter = typeMapper.mapSetterSignature(propertyDescriptor, OwnerKind.IMPLEMENTATION);
else
if(!(containingDeclaration instanceof JavaNamespaceDescriptor) && !(containingDeclaration instanceof JavaClassDescriptor)) {
JvmMethodSignature jvmMethodSignature = typeMapper.mapSetterSignature(propertyDescriptor, OwnerKind.IMPLEMENTATION);
setter = jvmMethodSignature != null ? jvmMethodSignature.getAsmMethod() : null;
} else {
setter = null;
}
}
}
@@ -1119,7 +1121,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
final CallableMethod callableMethod = (CallableMethod) callable;
invokeMethodWithArguments(callableMethod, expression, receiver);
final Type callReturnType = callableMethod.getSignature().getReturnType();
final Type callReturnType = callableMethod.getSignature().getAsmMethod().getReturnType();
return returnValueAsStackValue((FunctionDescriptor) fd, callReturnType);
}
else {
@@ -1478,7 +1480,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
pushTypeArguments(resolvedCall);
pushMethodArguments(resolvedCall, callableMethod.getValueParameterTypes());
callableMethod.invoke(v);
return returnValueAsStackValue((FunctionDescriptor) op, callableMethod.getSignature().getReturnType());
return returnValueAsStackValue((FunctionDescriptor) op, callableMethod.getSignature().getAsmMethod().getReturnType());
}
}
}
@@ -1850,7 +1852,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
CallableMethod callableMethod = (CallableMethod) callable;
genToJVMStack(expression.getBaseExpression());
callableMethod.invoke(v);
return returnValueAsStackValue((FunctionDescriptor) op, callableMethod.getSignature().getReturnType());
return returnValueAsStackValue((FunctionDescriptor) op, callableMethod.getSignature().getAsmMethod().getReturnType());
}
}
@@ -2115,7 +2117,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
else {
CallableMethod accessor = typeMapper.mapToCallableMethod(operationDescriptor, false, OwnerKind.IMPLEMENTATION);
boolean isGetter = accessor.getSignature().getName().equals("get");
boolean isGetter = accessor.getSignature().getAsmMethod().getName().equals("get");
ResolvedCall<FunctionDescriptor> resolvedSetCall = bindingContext.get(BindingContext.INDEXED_LVALUE_SET, expression);
ResolvedCall<FunctionDescriptor> resolvedGetCall = bindingContext.get(BindingContext.INDEXED_LVALUE_GET, expression);
@@ -2124,7 +2126,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
FunctionDescriptor getterDescriptor = resolvedGetCall == null ? null : resolvedGetCall.getResultingDescriptor();
Type asmType;
Type[] argumentTypes = accessor.getSignature().getArgumentTypes();
Type[] argumentTypes = accessor.getSignature().getAsmMethod().getArgumentTypes();
int index = 0;
if(isGetter) {
Callable callable = resolveToCallable(getterDescriptor, false);
@@ -2145,7 +2147,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
index++;
}
}
asmType = accessor.getSignature().getReturnType();
asmType = accessor.getSignature().getAsmMethod().getReturnType();
}
else {
assert resolvedSetCall != null;
@@ -9,6 +9,7 @@ import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.StdlibNames;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeProjection;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
@@ -17,6 +18,7 @@ import org.objectweb.asm.commons.InstructionAdapter;
import org.objectweb.asm.commons.Method;
import org.objectweb.asm.signature.SignatureVisitor;
import org.objectweb.asm.signature.SignatureWriter;
import org.objectweb.asm.util.CheckSignatureAdapter;
import java.util.List;
import java.util.Set;
@@ -44,19 +46,19 @@ public class FunctionCodegen {
public void gen(JetNamedFunction f) {
final FunctionDescriptor functionDescriptor = state.getBindingContext().get(BindingContext.FUNCTION, f);
assert functionDescriptor != null;
Method method = typeMapper.mapToCallableMethod(functionDescriptor, false, owner.getContextKind()).getSignature();
JvmMethodSignature method = typeMapper.mapToCallableMethod(functionDescriptor, false, owner.getContextKind()).getSignature();
generateMethod(f, method, functionDescriptor);
}
public void generateMethod(JetDeclarationWithBody f, Method jvmMethod, FunctionDescriptor functionDescriptor) {
public void generateMethod(JetDeclarationWithBody f, JvmMethodSignature jvmMethod, FunctionDescriptor functionDescriptor) {
CodegenContext.MethodContext funContext = owner.intoFunction(functionDescriptor);
final JetExpression bodyExpression = f.getBodyExpression();
generatedMethod(bodyExpression, jvmMethod, funContext, functionDescriptor, f);
}
private void generatedMethod(JetExpression bodyExpressions,
Method jvmSignature,
JvmMethodSignature jvmSignature,
CodegenContext.MethodContext context,
FunctionDescriptor functionDescriptor, JetDeclarationWithBody fun)
{
@@ -78,7 +80,7 @@ public class FunctionCodegen {
boolean isAbstract = !isStatic && !(kind == OwnerKind.TRAIT_IMPL) && (bodyExpressions == null || CodegenUtil.isInterface(functionDescriptor.getContainingDeclaration()));
if (isAbstract) flags |= ACC_ABSTRACT;
final MethodVisitor mv = v.newMethod(fun, flags, jvmSignature.getName(), jvmSignature.getDescriptor(), null, null);
final MethodVisitor mv = v.newMethod(fun, flags, jvmSignature.getAsmMethod().getName(), jvmSignature.getAsmMethod().getDescriptor(), jvmSignature.getGenericsSignature(), null);
if(v.generateCode()) {
int start = 0;
if(kind != OwnerKind.TRAIT_IMPL) {
@@ -128,9 +130,9 @@ public class FunctionCodegen {
FrameMap frameMap = context.prepareFrame(typeMapper);
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, jvmSignature.getReturnType(), context, state);
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, jvmSignature.getAsmMethod().getReturnType(), context, state);
Type[] argTypes = jvmSignature.getArgumentTypes();
Type[] argTypes = jvmSignature.getAsmMethod().getArgumentTypes();
int add = 0;
if(kind == OwnerKind.TRAIT_IMPL)
@@ -159,8 +161,8 @@ public class FunctionCodegen {
Type argType = argTypes[i];
iv.load(i + 1, argType);
}
iv.invokeinterface(dk.getOwnerClass(), jvmSignature.getName(), jvmSignature.getDescriptor());
iv.areturn(jvmSignature.getReturnType());
iv.invokeinterface(dk.getOwnerClass(), jvmSignature.getAsmMethod().getName(), jvmSignature.getAsmMethod().getDescriptor());
iv.areturn(jvmSignature.getAsmMethod().getReturnType());
}
else {
for (ValueParameterDescriptor parameter : paramDescrs) {
@@ -213,11 +215,11 @@ public class FunctionCodegen {
mv.visitMaxs(0, 0);
mv.visitEnd();
generateBridgeIfNeeded(owner, state, v, jvmSignature, functionDescriptor, kind);
generateBridgeIfNeeded(owner, state, v, jvmSignature.getAsmMethod(), functionDescriptor, kind);
}
}
generateDefaultIfNeeded(context, state, v, jvmSignature, functionDescriptor, kind);
generateDefaultIfNeeded(context, state, v, jvmSignature.getAsmMethod(), functionDescriptor, kind);
}
static void generateBridgeIfNeeded(CodegenContext owner, GenerationState state, ClassBuilder v, Method jvmSignature, FunctionDescriptor functionDescriptor, OwnerKind kind) {
@@ -383,7 +385,7 @@ public class FunctionCodegen {
Type type1 = state.getTypeMapper().mapType(overriddenFunction.getOriginal().getReturnType());
Type type2 = state.getTypeMapper().mapType(functionDescriptor.getReturnType());
if(!type1.equals(type2)) {
Method overriden = state.getTypeMapper().mapSignature(overriddenFunction.getName(), overriddenFunction.getOriginal());
Method overriden = state.getTypeMapper().mapSignature(overriddenFunction.getName(), overriddenFunction.getOriginal()).getAsmMethod();
int flags = ACC_PUBLIC; // TODO.
final MethodVisitor mv = v.newMethod(null, flags, jvmSignature.getName(), overriden.getDescriptor(), null, null);
@@ -146,7 +146,7 @@ public class GenerationState {
ConstructorDescriptor constructorDescriptor = closure.state.getBindingContext().get(BindingContext.CONSTRUCTOR, objectDeclaration);
CallableMethod callableMethod = closure.state.getTypeMapper().mapToCallableMethod(constructorDescriptor, OwnerKind.IMPLEMENTATION);
return new GeneratedAnonymousClassDescriptor(nameAndVisitor.first, callableMethod.getSignature(), objectContext.outerWasUsed, null);
return new GeneratedAnonymousClassDescriptor(nameAndVisitor.first, callableMethod.getSignature().getAsmMethod(), objectContext.outerWasUsed, null);
}
public static void prepareAnonymousClasses(JetElement aClass, final JetTypeMapper typeMapper) {
@@ -138,8 +138,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
FunctionDescriptor bridge = (FunctionDescriptor) entry.getValue();
FunctionDescriptor original = (FunctionDescriptor) entry.getKey();
Method method = typeMapper.mapSignature(bridge.getName(), bridge);
Method originalMethod = typeMapper.mapSignature(original.getName(), original);
Method method = typeMapper.mapSignature(bridge.getName(), bridge).getAsmMethod();
Method originalMethod = typeMapper.mapSignature(original.getName(), original).getAsmMethod();
Type[] argTypes = method.getArgumentTypes();
MethodVisitor mv = v.newMethod(null, Opcodes.ACC_PUBLIC|Opcodes.ACC_BRIDGE|Opcodes.ACC_FINAL, bridge.getName(), method.getDescriptor(), null, null);
@@ -166,8 +166,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
PropertyDescriptor bridge = (PropertyDescriptor) entry.getValue();
PropertyDescriptor original = (PropertyDescriptor) entry.getKey();
Method method = typeMapper.mapGetterSignature(bridge, OwnerKind.IMPLEMENTATION);
Method originalMethod = typeMapper.mapGetterSignature(original, OwnerKind.IMPLEMENTATION);
Method method = typeMapper.mapGetterSignature(bridge, OwnerKind.IMPLEMENTATION).getAsmMethod();
Method originalMethod = typeMapper.mapGetterSignature(original, OwnerKind.IMPLEMENTATION).getAsmMethod();
MethodVisitor mv = v.newMethod(null, Opcodes.ACC_PUBLIC|Opcodes.ACC_BRIDGE|Opcodes.ACC_FINAL, method.getName(), method.getDescriptor(), null, null);
InstructionAdapter iv = null;
if (v.generateCode()) {
@@ -186,8 +186,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
mv.visitEnd();
}
method = typeMapper.mapSetterSignature(bridge, OwnerKind.IMPLEMENTATION);
originalMethod = typeMapper.mapSetterSignature(original, OwnerKind.IMPLEMENTATION);
method = typeMapper.mapSetterSignature(bridge, OwnerKind.IMPLEMENTATION).getAsmMethod();
originalMethod = typeMapper.mapSetterSignature(original, OwnerKind.IMPLEMENTATION).getAsmMethod();
mv = v.newMethod(null, Opcodes.ACC_PUBLIC|Opcodes.ACC_BRIDGE|Opcodes.ACC_FINAL, method.getName(), method.getDescriptor(), null, null);
if (v.generateCode()) {
mv.visitCode();
@@ -283,11 +283,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
constructorMethod = new Method("<init>", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()]));
callableMethod = new CallableMethod("", constructorMethod, Opcodes.INVOKESPECIAL, Collections.<Type>emptyList());
callableMethod = new CallableMethod("", new JvmMethodSignature(constructorMethod, null) /* TODO */, Opcodes.INVOKESPECIAL, Collections.<Type>emptyList());
}
else {
callableMethod = typeMapper.mapToCallableMethod(constructorDescriptor, kind);
constructorMethod = callableMethod.getSignature();
constructorMethod = callableMethod.getSignature().getAsmMethod();
}
ObjectOrClosureCodegen closure = context.closure;
@@ -471,7 +471,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
mv.visitMaxs(0, 0);
mv.visitEnd();
FunctionCodegen.generateDefaultIfNeeded(constructorContext, state, v, constructorMethod, constructorDescriptor, OwnerKind.IMPLEMENTATION );
FunctionCodegen.generateDefaultIfNeeded(constructorContext, state, v, constructorMethod, constructorDescriptor, OwnerKind.IMPLEMENTATION);
}
private void generateTraitMethods(ExpressionCodegen codegen) {
@@ -490,8 +490,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
if(jetClass.isTrait()) {
int flags = Opcodes.ACC_PUBLIC; // TODO.
Method function = typeMapper.mapSignature(fun.getName(), fun);
Method functionOriginal = typeMapper.mapSignature(fun.getName(), fun.getOriginal());
Method function = typeMapper.mapSignature(fun.getName(), fun).getAsmMethod();
Method functionOriginal = typeMapper.mapSignature(fun.getName(), fun.getOriginal()).getAsmMethod();
final MethodVisitor mv = v.newMethod(myClass, flags, function.getName(), function.getDescriptor(), null, null);
if (v.generateCode()) {
@@ -629,7 +629,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
CallableMethod method = typeMapper.mapToCallableMethod(constructorDescriptor, kind);
int flags = Opcodes.ACC_PUBLIC; // TODO
final MethodVisitor mv = v.newMethod(constructor, flags, "<init>", method.getSignature().getDescriptor(), null, null);
final MethodVisitor mv = v.newMethod(constructor, flags, "<init>", method.getSignature().getAsmMethod().getDescriptor(), null, null);
if (v.generateCode()) {
mv.visitCode();
@@ -5,6 +5,7 @@ import jet.JetObject;
import jet.typeinfo.TypeInfo;
import jet.typeinfo.TypeInfoProjection;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
@@ -17,6 +18,9 @@ import org.jetbrains.jet.lexer.JetTokens;
import org.objectweb.asm.Opcodes;
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;
import java.util.*;
@@ -83,8 +87,6 @@ public class JetTypeMapper {
public static final Type TYPE_FLOAT_ITERATOR = Type.getObjectType("jet/FloatIterator");
public static final Type TYPE_DOUBLE_ITERATOR = Type.getObjectType("jet/DoubleIterator");
public static final Type TYPE_JET_PARAMETER = Type.getType(JetParameter.class);
public JetTypeMapper(JetStandardLibrary standardLibrary, BindingContext bindingContext) {
this.standardLibrary = standardLibrary;
this.bindingContext = bindingContext;
@@ -153,13 +155,23 @@ public class JetTypeMapper {
}
@NotNull public Type mapReturnType(final JetType jetType) {
return mapReturnType(jetType, null);
}
@NotNull private Type mapReturnType(final JetType jetType, @Nullable SignatureVisitor signatureVisitor) {
if (jetType.equals(JetStandardClasses.getUnitType()) || jetType.equals(JetStandardClasses.getNothingType())) {
if (signatureVisitor != null) {
signatureVisitor.visitBaseType('V');
}
return Type.VOID_TYPE;
}
if (jetType.equals(JetStandardClasses.getNullableNothingType())) {
if (signatureVisitor != null) {
visitAsmType(signatureVisitor, TYPE_OBJECT);
}
return TYPE_OBJECT;
}
return mapType(jetType, OwnerKind.IMPLEMENTATION);
return mapType(jetType, OwnerKind.IMPLEMENTATION, signatureVisitor);
}
private HashMap<DeclarationDescriptor,Map<DeclarationDescriptor,String>> naming = new HashMap<DeclarationDescriptor, Map<DeclarationDescriptor, String>>();
@@ -203,15 +215,28 @@ public class JetTypeMapper {
return name;
}
@NotNull public Type mapType(final JetType jetType) {
return mapType(jetType, OwnerKind.IMPLEMENTATION);
return mapType(jetType, (SignatureVisitor) null);
}
@NotNull private Type mapType(JetType jetType, @Nullable SignatureVisitor signatureVisitor) {
return mapType(jetType, OwnerKind.IMPLEMENTATION, signatureVisitor);
}
@NotNull public Type mapType(@NotNull final JetType jetType, OwnerKind kind) {
return mapType(jetType, kind, null);
}
@NotNull private Type mapType(JetType jetType, OwnerKind kind, @Nullable SignatureVisitor signatureVisitor) {
return mapType(jetType, kind, signatureVisitor, false);
}
@NotNull private Type mapType(JetType jetType, OwnerKind kind, @Nullable SignatureVisitor signatureVisitor, boolean typeParameter) {
Type known = knowTypes.get(jetType);
if(known != null)
return known;
if (known != null) {
return mapKnownAsmType(jetType, known, signatureVisitor, typeParameter);
}
DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
if (standardLibrary.getArray().equals(descriptor)) {
@@ -219,10 +244,18 @@ public class JetTypeMapper {
throw new UnsupportedOperationException("arrays must have one type argument");
}
JetType memberType = jetType.getArguments().get(0).getType();
if(!isGenericsArray(jetType))
if (signatureVisitor != null) {
SignatureVisitor arraySignatureVisitor = signatureVisitor.visitArrayType();
// TODO: box
mapType(memberType, kind, arraySignatureVisitor);
}
if (!isGenericsArray(jetType)) {
return Type.getType("[" + boxType(mapType(memberType, kind)).getDescriptor());
else
} else {
return ARRAY_GENERIC_TYPE;
}
}
if (JetStandardClasses.getAny().equals(descriptor)) {
@@ -230,16 +263,64 @@ public class JetTypeMapper {
}
if (descriptor instanceof ClassDescriptor) {
String name = getFQName(descriptor);
return Type.getObjectType(name + (kind == OwnerKind.TRAIT_IMPL ? "$$TImpl" : ""));
Type asmType = Type.getObjectType(name + (kind == OwnerKind.TRAIT_IMPL ? "$$TImpl" : ""));
if (signatureVisitor != null) {
signatureVisitor.visitClassType(asmType.getInternalName());
for (TypeProjection proj : jetType.getArguments()) {
// TODO: +-
SignatureVisitor argumentSignatureVisitor = signatureVisitor.visitTypeArgument('=');
mapType(proj.getType(), kind, argumentSignatureVisitor, true);
}
signatureVisitor.visitEnd();
}
return asmType;
}
if (descriptor instanceof TypeParameterDescriptor) {
if (signatureVisitor != null) {
TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) jetType.getConstructor().getDeclarationDescriptor();
signatureVisitor.visitTypeVariable(typeParameterDescriptor.getName());
}
return mapType(((TypeParameterDescriptor) descriptor).getUpperBoundsAsType(), kind);
}
throw new UnsupportedOperationException("Unknown type " + jetType);
}
private Type mapKnownAsmType(JetType jetType, Type asmType, @Nullable SignatureVisitor signatureVisitor, boolean genericTypeParameter) {
if (signatureVisitor != null) {
if (genericTypeParameter) {
visitAsmType(signatureVisitor, boxType(asmType));
} else {
visitAsmType(signatureVisitor, asmType);
}
}
return asmType;
}
private void visitAsmType(SignatureVisitor visitor, Type asmType) {
switch (asmType.getSort()) {
case Type.OBJECT:
visitor.visitClassType(asmType.getInternalName());
visitor.visitEnd();
return;
case Type.ARRAY:
SignatureVisitor elementSignatureVisitor = visitor.visitArrayType();
visitAsmType(elementSignatureVisitor, asmType.getElementType());
return;
default:
String descriptor = asmType.getDescriptor();
if (descriptor.length() != 1) {
throw new IllegalStateException();
}
visitor.visitBaseType(descriptor.charAt(0));
}
}
public static Type unboxType(final Type type) {
if (type == JL_INTEGER_TYPE) {
@@ -294,6 +375,7 @@ public class JetTypeMapper {
return asmType;
}
private static final boolean DEBUG_SIGNATURE_WRITER = true;
public CallableMethod mapToCallableMethod(FunctionDescriptor functionDescriptor, boolean superCall, OwnerKind kind) {
if(functionDescriptor == null)
@@ -301,7 +383,7 @@ public class JetTypeMapper {
final DeclarationDescriptor functionParent = functionDescriptor.getContainingDeclaration();
final List<Type> valueParameterTypes = new ArrayList<Type>();
Method descriptor = mapSignature(functionDescriptor.getOriginal(), valueParameterTypes, kind);
JvmMethodSignature descriptor = mapSignature(functionDescriptor.getOriginal(), true, valueParameterTypes, kind);
String owner;
int invokeOpcode;
ClassDescriptor thisClass;
@@ -328,7 +410,7 @@ public class JetTypeMapper {
? (superCall ? Opcodes.INVOKESTATIC : Opcodes.INVOKEINTERFACE)
: (superCall ? Opcodes.INVOKESPECIAL : Opcodes.INVOKEVIRTUAL);
if(isInterface && superCall) {
descriptor = mapSignature(functionDescriptor.getOriginal(), valueParameterTypes, OwnerKind.TRAIT_IMPL);
descriptor = mapSignature(functionDescriptor.getOriginal(), false, valueParameterTypes, OwnerKind.TRAIT_IMPL);
}
thisClass = (ClassDescriptor) functionParent;
}
@@ -345,7 +427,36 @@ public class JetTypeMapper {
return result;
}
private Method mapSignature(FunctionDescriptor f, List<Type> valueParameterTypes, OwnerKind kind) {
private JvmMethodSignature mapSignature(FunctionDescriptor f, boolean needGenericSignature, List<Type> valueParameterTypes, OwnerKind kind) {
for (ValueParameterDescriptor valueParameterDescriptor : f.getValueParameters()) {
if (valueParameterDescriptor.hasDefaultValue()) {
// TODO
needGenericSignature = false;
}
}
if (kind == OwnerKind.TRAIT_IMPL) {
needGenericSignature = false;
}
SignatureWriter signatureWriter = null;
SignatureVisitor signatureVisitor = null;
if (needGenericSignature) {
signatureWriter = new SignatureWriter();
signatureVisitor = DEBUG_SIGNATURE_WRITER ? new CheckSignatureAdapter(CheckSignatureAdapter.METHOD_SIGNATURE, signatureWriter) : signatureWriter;
}
for (TypeParameterDescriptor typeParameterDescriptor : f.getTypeParameters()) {
if (signatureVisitor != null) {
signatureVisitor.visitFormalTypeParameter(typeParameterDescriptor.getName());
SignatureVisitor classBoundVisitor = signatureVisitor.visitClassBound();
// TODO: wrong base
visitAsmType(classBoundVisitor, TYPE_OBJECT);
// TODO: interfaces
}
}
final ReceiverDescriptor receiverTypeRef = f.getReceiverParameter();
final JetType receiverType = !receiverTypeRef.exists() ? null : receiverTypeRef.getType();
final List<ValueParameterDescriptor> parameters = f.getValueParameters();
@@ -353,32 +464,36 @@ public class JetTypeMapper {
if(kind == OwnerKind.TRAIT_IMPL) {
ClassDescriptor containingDeclaration = (ClassDescriptor) f.getContainingDeclaration();
JetType jetType = TraitImplBodyCodegen.getSuperClass(containingDeclaration, bindingContext);
Type type = mapType(jetType);
Type type = mapType(jetType, signatureVisitor);
if(type.getInternalName().equals("java/lang/Object")) {
jetType = containingDeclaration.getDefaultType();
type = mapType(jetType);
type = mapType(jetType, signatureVisitor);
}
valueParameterTypes.add(type);
parameterTypes.add(type);
}
if (receiverType != null) {
parameterTypes.add(mapType(receiverType));
parameterTypes.add(mapType(receiverType, signatureVisitor != null ? signatureVisitor.visitParameterType() : null));
}
for (TypeParameterDescriptor parameterDescriptor : f.getTypeParameters()) {
if(parameterDescriptor.isReified()) {
parameterTypes.add(TYPE_TYPEINFO);
if (signatureVisitor != null) {
visitAsmType(signatureVisitor.visitParameterType(), TYPE_TYPEINFO);
}
}
}
for (ValueParameterDescriptor parameter : parameters) {
Type type = mapType(parameter.getOutType());
Type type = mapType(parameter.getOutType(), signatureVisitor != null ? signatureVisitor.visitParameterType() : null);
valueParameterTypes.add(type);
parameterTypes.add(type);
}
Type returnType = f instanceof ConstructorDescriptor ? Type.VOID_TYPE : mapReturnType(f.getReturnType());
return new Method(f.getName(), returnType, parameterTypes.toArray(new Type[parameterTypes.size()]));
Type returnType = f instanceof ConstructorDescriptor ? Type.VOID_TYPE : mapReturnType(f.getReturnType(), signatureVisitor != null ? signatureVisitor.visitReturnType() : null);
Method method = new Method(f.getName(), returnType, parameterTypes.toArray(new Type[parameterTypes.size()]));
return new JvmMethodSignature(method, signatureWriter != null ? signatureWriter.toString() : null);
}
public Method mapSignature(String name, FunctionDescriptor f) {
public JvmMethodSignature mapSignature(String name, FunctionDescriptor f) {
final ReceiverDescriptor receiver = f.getReceiverParameter();
final List<ValueParameterDescriptor> parameters = f.getValueParameters();
List<Type> parameterTypes = new ArrayList<Type>();
@@ -389,10 +504,12 @@ public class JetTypeMapper {
parameterTypes.add(mapType(parameter.getOutType()));
}
Type returnType = mapReturnType(f.getReturnType());
return new Method(name, returnType, parameterTypes.toArray(new Type[parameterTypes.size()]));
// TODO: proper generic signature
return new JvmMethodSignature(new Method(name, returnType, parameterTypes.toArray(new Type[parameterTypes.size()])), null);
}
public Method mapGetterSignature(PropertyDescriptor descriptor, OwnerKind kind) {
public JvmMethodSignature mapGetterSignature(PropertyDescriptor descriptor, OwnerKind kind) {
Type returnType = mapType(descriptor.getOutType());
String name = PropertyCodegen.getterName(descriptor.getName());
ArrayList<Type> params = new ArrayList<Type>();
@@ -412,10 +529,12 @@ public class JetTypeMapper {
}
}
return new Method(name, returnType, params.toArray(new Type[params.size()]));
// TODO: proper generic signature
return new JvmMethodSignature(new Method(name, returnType, params.toArray(new Type[params.size()])), null);
}
public Method mapSetterSignature(PropertyDescriptor descriptor, OwnerKind kind) {
@Nullable
public JvmMethodSignature mapSetterSignature(PropertyDescriptor descriptor, OwnerKind kind) {
JetType inType = descriptor.getInType();
if(inType == null)
return null;
@@ -440,10 +559,11 @@ public class JetTypeMapper {
params.add(mapType(inType));
return new Method(name, Type.VOID_TYPE, params.toArray(new Type[params.size()]));
// TODO: proper generic signature
return new JvmMethodSignature(new Method(name, Type.VOID_TYPE, params.toArray(new Type[params.size()])), null);
}
private Method mapConstructorSignature(ConstructorDescriptor descriptor, List<Type> valueParameterTypes) {
private JvmMethodSignature mapConstructorSignature(ConstructorDescriptor descriptor, List<Type> valueParameterTypes) {
List<ValueParameterDescriptor> parameters = descriptor.getOriginal().getValueParameters();
List<Type> parameterTypes = new ArrayList<Type>();
ClassDescriptor classDescriptor = descriptor.getContainingDeclaration();
@@ -463,12 +583,13 @@ public class JetTypeMapper {
valueParameterTypes.add(type);
}
return new Method("<init>", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()]));
Method method = new Method("<init>", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()]));
return new JvmMethodSignature(method, null); // TODO: generics signature
}
public CallableMethod mapToCallableMethod(ConstructorDescriptor descriptor, OwnerKind kind) {
List<Type> valueParameterTypes = new ArrayList<Type>();
final Method method = mapConstructorSignature(descriptor, valueParameterTypes);
final JvmMethodSignature method = mapConstructorSignature(descriptor, valueParameterTypes);
String owner = mapType(descriptor.getContainingDeclaration().getDefaultType(), kind).getInternalName();
return new CallableMethod(owner, method, INVOKESPECIAL, valueParameterTypes);
}
@@ -0,0 +1,28 @@
package org.jetbrains.jet.codegen;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.objectweb.asm.commons.Method;
/**
* @author Stepan Koltsov
*/
public class JvmMethodSignature {
private final Method asmMethod;
/** Null when we don't care about type parameters */
private final String genericsSignature;
public JvmMethodSignature(@NotNull Method asmMethod, @Nullable String genericsSignature) {
this.asmMethod = asmMethod;
this.genericsSignature = genericsSignature;
}
public Method getAsmMethod() {
return asmMethod;
}
public String getGenericsSignature() {
return genericsSignature;
}
}
@@ -133,7 +133,7 @@ public class PropertyCodegen {
if(isTrait && !(kind instanceof OwnerKind.DelegateKind))
flags |= Opcodes.ACC_ABSTRACT;
final String signature = state.getTypeMapper().mapGetterSignature(propertyDescriptor, kind).getDescriptor();
final String signature = state.getTypeMapper().mapGetterSignature(propertyDescriptor, kind).getAsmMethod().getDescriptor();
String getterName = getterName(propertyDescriptor.getName());
MethodVisitor mv = v.newMethod(origin, flags, getterName, signature, null, null);
if (v.generateCode() && (!isTrait || kind instanceof OwnerKind.DelegateKind)) {
@@ -179,7 +179,7 @@ public class PropertyCodegen {
if(isTrait && !(kind instanceof OwnerKind.DelegateKind))
flags |= Opcodes.ACC_ABSTRACT;
final String signature = state.getTypeMapper().mapSetterSignature(propertyDescriptor, kind).getDescriptor();
final String signature = state.getTypeMapper().mapSetterSignature(propertyDescriptor, kind).getAsmMethod().getDescriptor();
MethodVisitor mv = v.newMethod(origin, flags, setterName(propertyDescriptor.getName()), signature, null, null);
if (v.generateCode() && (!isTrait || kind instanceof OwnerKind.DelegateKind)) {
mv.visitCode();
@@ -29,6 +29,6 @@ public class PsiMethodCall implements IntrinsicMethod {
List<JetExpression> arguments, StackValue receiver) {
final CallableMethod callableMethod = codegen.getTypeMapper().mapToCallableMethod(myMethod, false, OwnerKind.IMPLEMENTATION);
codegen.invokeMethodWithArguments(callableMethod, (JetCallExpression) element, receiver);
return StackValue.onStack(callableMethod.getSignature().getReturnType());
return StackValue.onStack(callableMethod.getSignature().getAsmMethod().getReturnType());
}
}
@@ -0,0 +1,7 @@
class GenericArray {
public static void ggff() {
jet.typeinfo.TypeInfo noise = null;
String[] s = namespace.ffgg(noise, new String[0]);
}
}
@@ -0,0 +1 @@
fun <P> ffgg(a: Array<P>) = a
@@ -1,6 +1,6 @@
class Hello {
public static void xx() {
int x = namespace.f();
String s = namespace.f();
}
}
@@ -1 +1 @@
fun f() = 1
fun f() = "hello"
@@ -0,0 +1,6 @@
class Int {
{
int r = namespace.lll(1);
}
}
@@ -0,0 +1 @@
fun lll(a: Int) = a
@@ -0,0 +1,6 @@
class IntArray {
{
int[] r = namespace.doNothing(new int[0]);
}
}
@@ -0,0 +1 @@
fun doNothing(array: IntArray) = array
@@ -0,0 +1,6 @@
class IntWithDefault {
{
int r = namespace.www(1);
}
}
@@ -0,0 +1 @@
fun www(p: Int = 1) = p
@@ -0,0 +1,11 @@
import java.util.List;
import java.util.ArrayList;
class ListOfInt {
public static void hhh() {
List<Integer> list = new ArrayList<Integer>();
List<Integer> r = namespace.ggg(list);
}
}
@@ -0,0 +1,3 @@
import java.util.List
fun ggg(list: List<Int>) = list
@@ -0,0 +1,9 @@
import java.util.List;
import java.util.ArrayList;
class ListString {
public static void gg() {
List<String> list = new ArrayList<String>();
namespace.ff(list);
}
}
@@ -0,0 +1,3 @@
import java.util.List
fun ff(p: List<String>) = 1
@@ -0,0 +1,12 @@
import java.util.List;
import java.util.ArrayList;
class ListOfT {
public static void check() {
jet.typeinfo.TypeInfo nobodyCaresAboutTypeinfo = null;
List<String> list = new ArrayList<String>();
List<String> r = namespace.listOfT(nobodyCaresAboutTypeinfo, list);
}
}
@@ -0,0 +1,3 @@
import java.util.List
fun <P> listOfT(list: List<P>) = list
@@ -0,0 +1,13 @@
import java.util.Map;
import java.util.HashMap;
import java.math.BigDecimal;
class MapOfKString {
public static void gfgdgfg() {
jet.typeinfo.TypeInfo useless = null;
Map<BigDecimal, String> map = new HashMap<BigDecimal, String>();
Map<BigDecimal, String> r = namespace.fff(useless, map);
}
}
@@ -0,0 +1,3 @@
import java.util.Map
fun <K> fff(map: Map<K, String>) = map
@@ -0,0 +1,11 @@
import java.util.Map;
import java.util.HashMap;
import java.math.BigDecimal;
class MapOfKString {
public static void gfgdgfg() {
Map<String, Integer> map = new HashMap<String, Integer>();
Map<String, Integer> r = namespace.fff(map);
}
}
@@ -0,0 +1,3 @@
import java.util.Map
fun fff(map: Map<String, Int?>) = map
@@ -0,0 +1,5 @@
class Void {
{
namespace.f();
}
}
@@ -0,0 +1 @@
fun f() { }
@@ -95,7 +95,7 @@ public class CompileJavaAgainstKotlinTest extends UsefulTestCase {
try {
Iterable<? extends JavaFileObject> javaFileObjectsFromFiles = fileManager.getJavaFileObjectsFromFiles(Collections.singleton(javaFile));
List<String> options = Arrays.asList(
"-classpath", tmpdir.getPath(),
"-classpath", tmpdir.getPath() + System.getProperty("path.separator") + "out/production/stdlib",
"-d", tmpdir.getPath()
);
JavaCompiler.CompilationTask task = javaCompiler.getTask(null, fileManager, null, options, null, javaFileObjectsFromFiles);