diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java index 53af0cdc730..1b1bb5db25c 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java @@ -57,26 +57,18 @@ public class CodegenUtil { return (ClassDescriptor) outerDescriptor; } - public static boolean hasOuterTypeInfo(ClassDescriptor descriptor) { - ClassDescriptor outerClassDescriptor = getOuterClassDescriptor(descriptor); - if(outerClassDescriptor == null) - return false; - - if(outerClassDescriptor.getTypeConstructor().getParameters().size() > 0) - return true; - - return hasOuterTypeInfo(outerClassDescriptor); - } - - public static boolean hasDerivedTypeInfoField(JetType type, boolean exceptOwn) { - if(!exceptOwn) { - if(!isInterface(type)) - if(hasTypeInfoField(type)) - return true; + public static boolean hasDerivedTypeInfoField(JetType type) { + for (JetType jetType : type.getConstructor().getSupertypes()) { + if(hasTypeInfoField(jetType)) + return true; } - for (JetType jetType : type.getConstructor().getSupertypes()) { - if(hasDerivedTypeInfoField(jetType, false)) + return false; + } + + public static boolean requireTypeInfoConstructorArg(JetType type) { + for (TypeParameterDescriptor parameter : type.getConstructor().getParameters()) { + if(parameter.isReified()) return true; } @@ -87,22 +79,10 @@ public class CodegenUtil { if(isInterface(type)) return false; - List parameters = type.getConstructor().getParameters(); - for (TypeParameterDescriptor parameter : parameters) { - if(parameter.isReified()) - return true; - } + if(requireTypeInfoConstructorArg(type)) + return true; - for (JetType jetType : type.getConstructor().getSupertypes()) { - if(hasTypeInfoField(jetType)) - return true; - } - - ClassDescriptor outerClassDescriptor = getOuterClassDescriptor(type.getConstructor().getDeclarationDescriptor()); - if(outerClassDescriptor == null || isClassObject(type.getConstructor().getDeclarationDescriptor())) - return false; - - return hasTypeInfoField(outerClassDescriptor.getDefaultType()); + return hasDerivedTypeInfoField(type); } public static FunctionDescriptor createInvoke(ExpressionAsFunctionDescriptor fd) { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ConstructorFrameMap.java b/compiler/backend/src/org/jetbrains/jet/codegen/ConstructorFrameMap.java index b27e9ab18ce..9c60a5b170e 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ConstructorFrameMap.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ConstructorFrameMap.java @@ -12,11 +12,11 @@ import java.util.List; /** * @author yole + * @author alex.tkachman */ public class ConstructorFrameMap extends FrameMap { private int myOuterThisIndex = -1; - private int myFirstTypeParameter = -1; - private int myTypeParameterCount = 0; + private int myTypeInfoIndex = -1; public ConstructorFrameMap(CallableMethod callableMethod, @Nullable ConstructorDescriptor descriptor, ClassDescriptor classDescriptor, OwnerKind kind) { enterTemp(); // this @@ -27,15 +27,8 @@ public class ConstructorFrameMap extends FrameMap { } if (classDescriptor != null) { - List parameters = classDescriptor.getTypeConstructor().getParameters(); - for (TypeParameterDescriptor parameter : parameters) { - if(parameter.isReified()) { - int index = enterTemp(); - myTypeParameterCount++; - if(myFirstTypeParameter == -1) { - myFirstTypeParameter = index; - } - } + if (CodegenUtil.requireTypeInfoConstructorArg(classDescriptor.getDefaultType())) { + myTypeInfoIndex = enterTemp(); } } @@ -54,11 +47,7 @@ public class ConstructorFrameMap extends FrameMap { return myOuterThisIndex; } - public int getFirstTypeParameter() { - return myFirstTypeParameter; - } - - public int getTypeParameterCount() { - return myTypeParameterCount; + public int getTypeInfoIndex() { + return myTypeInfoIndex; } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index a24e486308e..d0644e6bd5a 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -979,7 +979,7 @@ public class ExpressionCodegen extends JetVisitor { } else if (descriptor instanceof TypeParameterDescriptor) { TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) descriptor; - loadTypeParameterTypeInfo(typeParameterDescriptor); + loadTypeParameterTypeInfo(typeParameterDescriptor, null); v.invokevirtual("jet/typeinfo/TypeInfo", "getClassObject", "()Ljava/lang/Object;"); v.checkcast(asmType(typeParameterDescriptor.getClassObjectType())); @@ -2033,26 +2033,32 @@ public class ExpressionCodegen extends JetVisitor { private void pushTypeArguments(ResolvedCall resolvedCall) { if(resolvedCall != null) { - Map typeArguments = resolvedCall.getTypeArguments(); - CallableDescriptor resultingDescriptor = resolvedCall.getCandidateDescriptor(); - for (TypeParameterDescriptor typeParameterDescriptor : resultingDescriptor.getTypeParameters()) { - if(typeParameterDescriptor.isReified()) { - JetType jetType = typeArguments.get(typeParameterDescriptor); - generateTypeInfo(jetType); + if(resolvedCall.getResultingDescriptor() instanceof ConstructorDescriptor) { + ConstructorDescriptor constructorDescriptor = (ConstructorDescriptor) resolvedCall.getResultingDescriptor(); + ClassDescriptor containingDeclaration = constructorDescriptor.getContainingDeclaration(); + if(CodegenUtil.requireTypeInfoConstructorArg(containingDeclaration.getDefaultType())) { + generateTypeInfo(containingDeclaration.getDefaultType(), resolvedCall.getTypeArguments()); + } + } + else { + Map typeArguments = resolvedCall.getTypeArguments(); + CallableDescriptor resultingDescriptor = resolvedCall.getCandidateDescriptor(); + for (TypeParameterDescriptor typeParameterDescriptor : resultingDescriptor.getTypeParameters()) { + if(typeParameterDescriptor.isReified()) { + JetType jetType = typeArguments.get(typeParameterDescriptor); + generateTypeInfo(jetType, typeArguments); + } } } } else { throw new UnsupportedOperationException(); -// for (JetTypeProjection jetTypeArgument : expression.getTypeArguments()) { -// pushTypeArgument(jetTypeArgument); -// } } } public void pushTypeArgument(JetTypeProjection jetTypeArgument) { JetType typeArgument = bindingContext.get(BindingContext.TYPE, jetTypeArgument.getTypeReference()); - generateTypeInfo(typeArgument); + generateTypeInfo(typeArgument, null); } private Type generateJavaConstructorCall(JetCallExpression expression) { @@ -2091,7 +2097,7 @@ public class ExpressionCodegen extends JetVisitor { if(isArray) { JetType elementType = typeMapper.getGenericsElementType(arrayType); if(elementType != null) { - generateTypeInfo(elementType); + generateTypeInfo(elementType, null); gen(args.get(0).getArgumentExpression(), Type.INT_TYPE); v.invokevirtual("jet/typeinfo/TypeInfo", "newArray", "(I)[Ljava/lang/Object;"); } @@ -2195,7 +2201,7 @@ public class ExpressionCodegen extends JetVisitor { } for (TypeParameterDescriptor typeParameterDescriptor : getterDescriptor.getTypeParameters()) { if(typeParameterDescriptor.isReified()) { - generateTypeInfo(resolvedGetCall.getTypeArguments().get(typeParameterDescriptor)); + generateTypeInfo(resolvedGetCall.getTypeArguments().get(typeParameterDescriptor), null); index++; } } @@ -2215,7 +2221,7 @@ public class ExpressionCodegen extends JetVisitor { } for (TypeParameterDescriptor typeParameterDescriptor : setterDescriptor.getOriginal().getTypeParameters()) { if(typeParameterDescriptor.isReified()) { - generateTypeInfo(resolvedSetCall.getTypeArguments().get(typeParameterDescriptor)); + generateTypeInfo(resolvedSetCall.getTypeArguments().get(typeParameterDescriptor), null); index++; } } @@ -2503,7 +2509,7 @@ If finally block is present, its last expression is the value of try expression. } } else { - generateTypeInfo(jetType); + generateTypeInfo(jetType, null); expressionToGen.put(TYPE_OBJECT, v); if (leaveExpressionOnStack) { v.dupX1(); @@ -2512,7 +2518,7 @@ If finally block is present, its last expression is the value of try expression. } } - public void generateTypeInfo(JetType jetType) { + public void generateTypeInfo(JetType jetType, Map typeArguments) { String knownTypeInfo = typeMapper.isKnownTypeInfo(jetType); if(knownTypeInfo != null) { v.getstatic("jet/typeinfo/TypeInfo", knownTypeInfo, "Ljet/typeinfo/TypeInfo;"); @@ -2521,7 +2527,7 @@ If finally block is present, its last expression is the value of try expression. DeclarationDescriptor declarationDescriptor = jetType.getConstructor().getDeclarationDescriptor(); if (declarationDescriptor instanceof TypeParameterDescriptor) { - loadTypeParameterTypeInfo((TypeParameterDescriptor) declarationDescriptor); + loadTypeParameterTypeInfo((TypeParameterDescriptor) declarationDescriptor, typeArguments); return; } @@ -2551,7 +2557,7 @@ If finally block is present, its last expression is the value of try expression. TypeProjection argument = arguments.get(i); v.dup(); v.iconst(i); - generateTypeInfo(argument.getType()); + generateTypeInfo(argument.getType(), typeArguments); genTypeInfoToProjection(v, argument.getProjectionKind()); v.astore(TYPE_OBJECT); } @@ -2573,12 +2579,21 @@ If finally block is present, its last expression is the value of try expression. throw new UnsupportedOperationException(variance.toString()); } - private void loadTypeParameterTypeInfo(TypeParameterDescriptor typeParameterDescriptor) { + private void loadTypeParameterTypeInfo(TypeParameterDescriptor typeParameterDescriptor, @Nullable Map typeArguments) { final StackValue value = typeParameterExpressions.get(typeParameterDescriptor); if (value != null) { value.put(TYPE_TYPEINFO, v); return; } + + if(typeArguments != null) { + JetType jetType = typeArguments.get(typeParameterDescriptor); + if(jetType != null && !jetType.equals(typeParameterDescriptor.getDefaultType())) { + generateTypeInfo(jetType, typeArguments); + return; + } + } + DeclarationDescriptor containingDeclaration = typeParameterDescriptor.getContainingDeclaration(); if (context.getThisDescriptor() != null) { ClassDescriptor descriptor = context.getThisDescriptor(); @@ -2589,8 +2604,13 @@ If finally block is present, its last expression is the value of try expression. if (containingDeclaration == context.getThisDescriptor()) { if(!CodegenUtil.isInterface(descriptor)) { if (CodegenUtil.hasTypeInfoField(defaultType)) { - v.load(0, TYPE_OBJECT); - v.getfield(ownerType.getInternalName(), "$typeInfo", "Ljet/typeinfo/TypeInfo;"); + if(!(context instanceof CodegenContext.ConstructorContext)) { + v.load(0, TYPE_OBJECT); + v.getfield(ownerType.getInternalName(), "$typeInfo", "Ljet/typeinfo/TypeInfo;"); + } + else { + v.load(1, TYPE_OBJECT); + } } else { v.getstatic(ownerType.getInternalName(), "$typeInfo", "Ljet/typeinfo/TypeInfo;"); @@ -2603,11 +2623,11 @@ If finally block is present, its last expression is the value of try expression. } else { v.load(0, TYPE_OBJECT); - v.invokeinterface("jet/JetObject", "getTypeInfo", "()Ljet/typeinfo/TypeInfo;"); while(descriptor != containingDeclaration) { descriptor = CodegenUtil.getOuterClassDescriptor(descriptor); - v.invokevirtual("jet/typeinfo/TypeInfo", "getOuterTypeInfo", "()Ljet/typeinfo/TypeInfo;"); + v.invokeinterface("jet/JetObject", "getOuterObject", "()Ljet/JetObject;"); } + v.invokeinterface("jet/JetObject", "getTypeInfo", "()Ljet/typeinfo/TypeInfo;"); } v.aconst(ownerType); v.iconst(typeParameterDescriptor.getIndex()); @@ -2737,7 +2757,7 @@ If finally block is present, its last expression is the value of try expression. v.anew(tupleType); v.dup(); - generateTypeInfo(new ProjectionErasingJetType(bindingContext.get(BindingContext.EXPRESSION_TYPE, expression))); + generateTypeInfo(new ProjectionErasingJetType(bindingContext.get(BindingContext.EXPRESSION_TYPE, expression)), null); for (JetExpression entry : entries) { gen(entry, TYPE_OBJECT); } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index 312f297acc6..a637350f361 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -305,8 +305,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { parameterTypes.add(typeMapper.mapType(CodegenUtil.getOuterClassDescriptor(descriptor).getDefaultType(), OwnerKind.IMPLEMENTATION)); } - List typeParameters = descriptor.getTypeConstructor().getParameters(); - for (int n = typeParameters.size(); n > 0; n--) { + if (CodegenUtil.requireTypeInfoConstructorArg(descriptor.getDefaultType())) { parameterTypes.add(JetTypeMapper.TYPE_TYPEINFO); } @@ -365,12 +364,12 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { final InstructionAdapter iv = new InstructionAdapter(mv); ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, constructorContext, state); - for(int slot = 0; slot != frameMap.getTypeParameterCount(); ++slot) { - if(constructorDescriptor != null) - codegen.addTypeParameter(constructorDescriptor.getTypeParameters().get(slot), StackValue.local(frameMap.getFirstTypeParameter() + slot, JetTypeMapper.TYPE_TYPEINFO)); - else - codegen.addTypeParameter(descriptor.getTypeConstructor().getParameters().get(slot), StackValue.local(frameMap.getFirstTypeParameter() + slot, JetTypeMapper.TYPE_TYPEINFO)); - } +// for(int slot = 0; slot != frameMap.getTypeParameterCount(); ++slot) { +// if(constructorDescriptor != null) +// codegen.addTypeParameter(constructorDescriptor.getTypeParameters().get(slot), StackValue.local(frameMap.getFirstTypeParameter() + slot, JetTypeMapper.TYPE_TYPEINFO)); +// else +// codegen.addTypeParameter(descriptor.getTypeConstructor().getParameters().get(slot), StackValue.local(frameMap.getFirstTypeParameter() + slot, JetTypeMapper.TYPE_TYPEINFO)); +// } String classname = typeMapper.mapType(descriptor.getDefaultType(), kind).getInternalName(); final Type classType = Type.getType("L" + classname + ";"); @@ -399,7 +398,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { parameterTypes.add(typeMapper.mapType(CodegenUtil.getOuterClassDescriptor(descriptor).getDefaultType(), OwnerKind.IMPLEMENTATION)); } for(TypeProjection typeParameterDescriptor : superType.getArguments()) { - codegen.generateTypeInfo(typeParameterDescriptor.getType()); + codegen.generateTypeInfo(typeParameterDescriptor.getType(), null); parameterTypes.add(JetTypeMapper.TYPE_TYPEINFO); } Method superCallMethod = new Method("", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()])); @@ -447,10 +446,21 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { iv.load(0, classType); iv.load(frameMap.getOuterThisIndex(), type); iv.putfield(classname, fieldName, interfaceDesc); + + Type outerType = typeMapper.mapType(outerDescriptor.getDefaultType()); + MethodVisitor outer = v.newMethod(myClass, Opcodes.ACC_PUBLIC, "getOuterObject", "()Ljet/JetObject;", null, null); + outer.visitCode(); + outer.visitVarInsn(Opcodes.ALOAD, 0); + outer.visitFieldInsn(Opcodes.GETFIELD, classname, "this$0", outerType.getDescriptor()); + outer.visitInsn(Opcodes.ARETURN); + outer.visitMaxs(0, 0); + outer.visitEnd(); } - if (CodegenUtil.hasTypeInfoField(descriptor.getDefaultType()) && kind == OwnerKind.IMPLEMENTATION) { - generateTypeInfoInitializer(frameMap.getFirstTypeParameter(), frameMap.getTypeParameterCount(), iv); + if (CodegenUtil.requireTypeInfoConstructorArg(descriptor.getDefaultType()) && kind == OwnerKind.IMPLEMENTATION) { + iv.load(0, JetTypeMapper.TYPE_OBJECT); + iv.load(frameMap.getTypeInfoIndex(), JetTypeMapper.TYPE_OBJECT); + iv.invokevirtual(typeMapper.mapType(descriptor.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName(), "$setTypeInfo", "(Ljet/typeinfo/TypeInfo;)V"); } if(closure != null) { @@ -691,46 +701,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { } } - protected void generateTypeInfoInitializer(int firstTypeParameter, int typeParamCount, InstructionAdapter iv) { - iv.load(0, JetTypeMapper.TYPE_OBJECT); - - iv.aconst(typeMapper.mapType(descriptor.getDefaultType(), OwnerKind.IMPLEMENTATION)); - iv.iconst(0); - - if(CodegenUtil.hasOuterTypeInfo(descriptor)) { - iv.load(1, JetTypeMapper.TYPE_OBJECT); - iv.invokeinterface("jet/JetObject", "getTypeInfo", "()Ljet/typeinfo/TypeInfo;"); - } - - if(typeParamCount != 0) { - iv.iconst(typeParamCount); - iv.newarray(JetTypeMapper.TYPE_TYPEINFOPROJECTION); - - for (int i = 0; i < typeParamCount; i++) { - iv.dup(); - iv.iconst(i); - iv.load(firstTypeParameter + i, JetTypeMapper.TYPE_OBJECT); - iv.checkcast(JetTypeMapper.TYPE_TYPEINFOPROJECTION); - iv.astore(JetTypeMapper.TYPE_OBJECT); - } - - if(CodegenUtil.hasOuterTypeInfo(descriptor)) { - iv.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;ZLjet/typeinfo/TypeInfo;[Ljet/typeinfo/TypeInfoProjection;)Ljet/typeinfo/TypeInfo;"); - } - else - iv.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;Z[Ljet/typeinfo/TypeInfoProjection;)Ljet/typeinfo/TypeInfo;"); - } - else { - if(CodegenUtil.hasOuterTypeInfo(descriptor)) { - iv.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;ZLjet/typeinfo/TypeInfo;)Ljet/typeinfo/TypeInfo;"); - } - else - iv.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;Z)Ljet/typeinfo/TypeInfo;"); - } - - iv.invokevirtual(typeMapper.mapType(descriptor.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName(), "$setTypeInfo", "(Ljet/typeinfo/TypeInfo;)V"); - } - protected void generateInitializers(ExpressionCodegen codegen, InstructionAdapter iv) { for (JetDeclaration declaration : myClass.getDeclarations()) { if (declaration instanceof JetProperty) { @@ -827,15 +797,14 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { return; JetType defaultType = descriptor.getDefaultType(); - if(CodegenUtil.hasTypeInfoField(defaultType)) { - if(!CodegenUtil.hasDerivedTypeInfoField(defaultType, true)) { + if(CodegenUtil.requireTypeInfoConstructorArg(defaultType)) { + if(!CodegenUtil.hasDerivedTypeInfoField(defaultType)) { v.newField(myClass, Opcodes.ACC_PROTECTED, "$typeInfo", "Ljet/typeinfo/TypeInfo;", null, null); MethodVisitor mv = v.newMethod(myClass, Opcodes.ACC_PUBLIC, "getTypeInfo", "()Ljet/typeinfo/TypeInfo;", null, null); - InstructionAdapter iv = null; if (v.generateCode()) { mv.visitCode(); - iv = new InstructionAdapter(mv); + InstructionAdapter iv = new InstructionAdapter(mv); String owner = typeMapper.mapType(descriptor.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName(); iv.load(0, JetTypeMapper.TYPE_OBJECT); iv.getfield(owner, "$typeInfo", "Ljet/typeinfo/TypeInfo;"); @@ -847,7 +816,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { mv = v.newMethod(myClass, Opcodes.ACC_PROTECTED | Opcodes.ACC_FINAL, "$setTypeInfo", "(Ljet/typeinfo/TypeInfo;)V", null, null); if (v.generateCode()) { mv.visitCode(); - iv = new InstructionAdapter(mv); + InstructionAdapter iv = new InstructionAdapter(mv); String owner = typeMapper.mapType(descriptor.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName(); iv.load(0, JetTypeMapper.TYPE_OBJECT); iv.load(1, JetTypeMapper.TYPE_OBJECT); @@ -884,14 +853,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { public void generate(InstructionAdapter v) { v.aconst(typeMapper.mapType(descriptor.getDefaultType(), OwnerKind.IMPLEMENTATION)); v.iconst(0); - ClassDescriptor outerClassDescriptor = CodegenUtil.getOuterClassDescriptor(descriptor); - if(outerClassDescriptor == null || CodegenUtil.isClassObject(descriptor)) { - v.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;Z)Ljet/typeinfo/TypeInfo;"); - } - else { - v.getstatic(typeMapper.mapType(outerClassDescriptor.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName(), "$staticTypeInfo", "Ljet/typeinfo/TypeInfo;"); - v.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;ZLjet/typeinfo/TypeInfo;)Ljet/typeinfo/TypeInfo;"); - } + v.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;Z)Ljet/typeinfo/TypeInfo;"); v.putstatic(typeMapper.mapType(descriptor.getDefaultType(), kind).getInternalName(), "$staticTypeInfo", "Ljet/typeinfo/TypeInfo;"); } }); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java index 06b23293f82..0e62029178e 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java @@ -86,7 +86,11 @@ public class JetTypeMapper { public static final Type TYPE_LONG_ITERATOR = Type.getObjectType("jet/LongIterator"); public static final Type TYPE_FLOAT_ITERATOR = Type.getObjectType("jet/FloatIterator"); public static final Type TYPE_DOUBLE_ITERATOR = Type.getObjectType("jet/DoubleIterator"); - + + public JetStandardLibrary getStandardLibrary() { + return standardLibrary; + } + public JetTypeMapper(JetStandardLibrary standardLibrary, BindingContext bindingContext) { this.standardLibrary = standardLibrary; this.bindingContext = bindingContext; @@ -575,10 +579,8 @@ public class JetTypeMapper { parameterTypes.add(mapType(CodegenUtil.getOuterClassDescriptor(classDescriptor).getDefaultType(), OwnerKind.IMPLEMENTATION)); } - List typeParameters = classDescriptor.getTypeConstructor().getParameters(); - for (TypeParameterDescriptor typeParameter : typeParameters) { - if(typeParameter.isReified()) - parameterTypes.add(TYPE_TYPEINFO); + if (CodegenUtil.requireTypeInfoConstructorArg(classDescriptor.getDefaultType())) { + parameterTypes.add(TYPE_TYPEINFO); } for (ValueParameterDescriptor parameter : parameters) { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java index 837c1503717..9a6f2c5210a 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java @@ -6,6 +6,7 @@ import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.java.JavaClassDescriptor; +import org.jetbrains.jet.lang.types.JetStandardClasses; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.TypeProjection; import org.jetbrains.jet.lang.types.TypeUtils; @@ -145,7 +146,7 @@ public class NamespaceCodegen { } DeclarationDescriptor declarationDescriptor = jetType.getConstructor().getDeclarationDescriptor(); - if(!jetType.equals(root) && jetType.getArguments().size() == 0 && !(declarationDescriptor instanceof JavaClassDescriptor)) { + if(!jetType.equals(root) && jetType.getArguments().size() == 0 && !(declarationDescriptor instanceof JavaClassDescriptor) && !JetStandardClasses.getAny().equals(declarationDescriptor)) { // TODO: we need some better checks here v.getstatic(typeMapper.mapType(jetType, OwnerKind.IMPLEMENTATION).getInternalName(), "$typeInfo", "Ljet/typeinfo/TypeInfo;"); return; diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java b/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java index d8591fe5e4a..f9167601b55 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java @@ -7,6 +7,7 @@ import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.resolve.calls.ResolvedCall; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; +import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lexer.JetTokens; import org.objectweb.asm.Label; import org.objectweb.asm.Opcodes; @@ -629,7 +630,7 @@ public abstract class StackValue { for (TypeParameterDescriptor typeParameterDescriptor : setterDescriptor.getOriginal().getTypeParameters()) { if(typeParameterDescriptor.isReified()) { - codegen.generateTypeInfo(resolvedSetCall.getTypeArguments().get(typeParameterDescriptor)); + codegen.generateTypeInfo(resolvedSetCall.getTypeArguments().get(typeParameterDescriptor), null); } } @@ -1010,7 +1011,8 @@ public abstract class StackValue { return codegen.typeMapper.mapType(callableMethod.getReceiverClass()); } else { - return codegen.typeMapper.mapType(callableMethod.getThisType()); + JetType thisType = callableMethod.getThisType(); + return codegen.typeMapper.mapType(thisType); } } else { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/ArrayIterator.java b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/ArrayIterator.java index 4c0f906e5ab..8fcd6d57500 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/ArrayIterator.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/ArrayIterator.java @@ -5,14 +5,12 @@ import org.jetbrains.jet.codegen.ExpressionCodegen; import org.jetbrains.jet.codegen.JetTypeMapper; import org.jetbrains.jet.codegen.StackValue; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; -import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.psi.JetCallExpression; import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetSimpleNameExpression; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.types.JetStandardLibrary; -import org.jetbrains.jet.lang.types.JetType; import org.objectweb.asm.Type; import org.objectweb.asm.commons.InstructionAdapter; @@ -30,7 +28,7 @@ public class ArrayIterator implements IntrinsicMethod { ClassDescriptor containingDeclaration = (ClassDescriptor) funDescriptor.getContainingDeclaration().getOriginal(); JetStandardLibrary standardLibrary = codegen.getState().getStandardLibrary(); if(containingDeclaration.equals(standardLibrary.getArray())) { - codegen.generateTypeInfo(funDescriptor.getReturnType().getArguments().get(0).getType()); + codegen.generateTypeInfo(funDescriptor.getReturnType().getArguments().get(0).getType(), null); v.invokestatic("jet/runtime/ArrayIterator", "iterator", "([Ljava/lang/Object;Ljet/typeinfo/TypeInfo;)Ljet/Iterator;"); return StackValue.onStack(JetTypeMapper.TYPE_ITERATOR); } diff --git a/compiler/testData/codegen/regressions/kt259.jet b/compiler/testData/codegen/regressions/kt259.jet index 59a99b1bcbb..ad996781b9f 100644 --- a/compiler/testData/codegen/regressions/kt259.jet +++ b/compiler/testData/codegen/regressions/kt259.jet @@ -1,4 +1,5 @@ class A() {} + open class B() { fun isT (a : Any?) : Boolean { return a is T @@ -167,7 +168,6 @@ fun t26 () : Boolean { } fun box() : String { -/* if(!t1()) { return "t1 failed" } @@ -243,7 +243,6 @@ fun box() : String { if(!t25()) { return "t25 failed" } - */ if(!t26()) { return "t26 failed" } diff --git a/compiler/testData/codegen/regressions/kt785.jet b/compiler/testData/codegen/regressions/kt785.jet new file mode 100644 index 00000000000..1b10c8c73d7 --- /dev/null +++ b/compiler/testData/codegen/regressions/kt785.jet @@ -0,0 +1,13 @@ +class A() { + var x : Int = 0 + + var z = { () => + x++ + } +} + +fun box() : String { + val a = A() + a.z() //problem is here + return if (a.x == 1) "OK" else "fail" +} \ No newline at end of file diff --git a/compiler/testData/codegen/typeInfo/inheritance.jet b/compiler/testData/codegen/typeInfo/inheritance.jet index 225bda1f665..3ee02657f34 100644 --- a/compiler/testData/codegen/typeInfo/inheritance.jet +++ b/compiler/testData/codegen/typeInfo/inheritance.jet @@ -1,4 +1,4 @@ -open class A () { +open class A () { fun plus(e: T) = B (e) } @@ -6,4 +6,6 @@ class B (val e: T) : A() { fun add() = B (e) } -fun box() = if( A().plus("239").add().e == "239" ) "OK" else "fail" \ No newline at end of file +fun box() : String { + return if(A().plus("239").add().e == "239" ) "OK" else "fail" +} \ No newline at end of file diff --git a/compiler/testData/codegen/typeInfo/inner.jet b/compiler/testData/codegen/typeInfo/inner.jet index 49db9252b35..62dad284a09 100644 --- a/compiler/testData/codegen/typeInfo/inner.jet +++ b/compiler/testData/codegen/typeInfo/inner.jet @@ -4,7 +4,6 @@ class Box() { } class Inner2() : Inner() { - } fun inner() = Inner2() diff --git a/compiler/tests/org/jetbrains/jet/codegen/ClassGenTest.java b/compiler/tests/org/jetbrains/jet/codegen/ClassGenTest.java index 25c697c6484..88e445a6bb1 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/ClassGenTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/ClassGenTest.java @@ -24,7 +24,7 @@ public class ClassGenTest extends CodegenTestCase { public void testArrayListInheritance() throws Exception { loadFile("classes/inheritingFromArrayList.jet"); - + System.out.println(generateToText()); final Class aClass = loadClass("Foo", generateClassesInFile()); assertInstanceOf(aClass.newInstance(), List.class); } diff --git a/compiler/tests/org/jetbrains/jet/codegen/FunctionGenTest.java b/compiler/tests/org/jetbrains/jet/codegen/FunctionGenTest.java index 7b5a7a33e7a..431400d66bd 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/FunctionGenTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/FunctionGenTest.java @@ -81,6 +81,10 @@ public class FunctionGenTest extends CodegenTestCase { blackBoxFile("regressions/kt395.jet"); } + public void testKt785 () { +// blackBoxFile("regressions/kt785.jet"); + } + public void testFunction () throws InvocationTargetException, IllegalAccessException { blackBoxFile("functions/functionExpression.jet"); } diff --git a/compiler/tests/org/jetbrains/jet/codegen/TypeInfoTest.java b/compiler/tests/org/jetbrains/jet/codegen/TypeInfoTest.java index 85b9dae07d8..b2396c96af6 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/TypeInfoTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/TypeInfoTest.java @@ -140,7 +140,7 @@ public class TypeInfoTest extends CodegenTestCase { public void testInner() throws Exception { blackBoxFile("typeInfo/inner.jet"); -// System.out.println(generateToText()); + System.out.println(generateToText()); } public void testInheritance() throws Exception { @@ -148,4 +148,3 @@ public class TypeInfoTest extends CodegenTestCase { System.out.println(generateToText()); } } - diff --git a/examples/src/benchmarks/FList.java b/examples/src/benchmarks/FList.java new file mode 100644 index 00000000000..694dd70ac96 --- /dev/null +++ b/examples/src/benchmarks/FList.java @@ -0,0 +1,86 @@ +import java.util.NoSuchElementException; + +abstract public class FList { + abstract T getHead(); + + abstract FList getTail(); + + abstract FList plus(T element); + + static class Empty extends FList { + + @Override + T getHead() { + throw new NoSuchElementException(); + } + + @Override + FList getTail() { + throw new NoSuchElementException(); + } + + @Override + FList plus(T element) { + return new OneElementList(element); + } + } + + static class OneElementList extends FList { + private T element; + + public OneElementList(T element) { + super(); + this.element = element; + } + + @Override + T getHead() { + return element; + } + + @Override + FList getTail() { + return new Empty(); + } + + @Override + FList plus(T element) { + return new StandardList(element, this); + } + } + + private static class StandardList extends FList { + private T head; + private FList tail; + + public StandardList(T head, FList tail) { + this.head = head; + this.tail = tail; + } + + @Override + T getHead() { + return head; + } + + @Override + FList getTail() { + return tail; + } + + @Override + FList plus(T element) { + return new StandardList(element, this); + } + } + + public static void main(String[] args) { + for(int k = 0; k != 10; ++k) { + long start = System.currentTimeMillis(); + FList list = new Empty(); + for(int i = 0; i != 5000000; ++i) + list = list.plus(i); + System.out.println(System.currentTimeMillis()-start); + } + } +} diff --git a/examples/src/benchmarks/FList.kt b/examples/src/benchmarks/FList.kt new file mode 100644 index 00000000000..5d806215920 --- /dev/null +++ b/examples/src/benchmarks/FList.kt @@ -0,0 +1,70 @@ +namespace flist + +abstract class FList { + abstract val head : T + abstract val tail : FList + + abstract fun plus(element: T) : FList +} + +class EmptyFList() : FList { + override val head: T + get() = throw java.util.NoSuchElementException() + + override val tail : EmptyFList + get() = EmptyFList() + + override fun plus(element: T) : FList = OneElementFList(element) +} + +class OneElementFList (override val head: T): FList { + override val tail : EmptyFList + get() = EmptyFList() + + override fun plus(element: T) : FList = StandardFList(element, this) +} + +class StandardFList (override val head: T, override val tail: FList) : FList { + override fun plus(element: T) : FList = StandardFList(element, this) +} + +fun FList.plus2(element: T): FList = + when(this) { + is EmptyFList => OneElementFList(element) + else => StandardFList(element, this) + } + +fun FList.plus3(element: T) : FList = + if(this is EmptyFList<*>) + OneElementFList(element) + else + StandardFList(element, this) + +fun main(args: Array) { + for(k in 0..3) { + val start0 = System.currentTimeMillis() + + var flist0 : FList = EmptyFList() + for(i in 0..5000000) + flist0 = flist0 + i + + System.out?.println(System.currentTimeMillis() - start0) + + val start = System.currentTimeMillis() + + var flist : FList = EmptyFList() + for(i in 0..5000000) + flist = flist.plus2(i) + + System.out?.println(System.currentTimeMillis() - start) + + val start2 = System.currentTimeMillis() + + var flist2 : FList = EmptyFList() + for(i in 0..5000000) + flist2 = flist2.plus3(i) + + System.out?.println(System.currentTimeMillis() - start2) + System.out?.println() + } +} \ No newline at end of file diff --git a/stdlib/src/jet/DefaultJetObject.java b/stdlib/src/jet/DefaultJetObject.java index 4070c14eb5d..736606a70d6 100644 --- a/stdlib/src/jet/DefaultJetObject.java +++ b/stdlib/src/jet/DefaultJetObject.java @@ -23,4 +23,9 @@ public class DefaultJetObject implements JetObject { public final TypeInfo getTypeInfo() { return typeInfo; } + + @Override + public JetObject getOuterObject() { + return null; + } } diff --git a/stdlib/src/jet/IntRange.java b/stdlib/src/jet/IntRange.java index 71d49ed0a73..13811dbba40 100644 --- a/stdlib/src/jet/IntRange.java +++ b/stdlib/src/jet/IntRange.java @@ -47,7 +47,12 @@ public final class IntRange implements Range, Iterable, JetObj public TypeInfo getTypeInfo() { return typeInfo; } - + + @Override + public JetObject getOuterObject() { + return null; + } + public static IntRange count(int length) { return new IntRange(0, length); } @@ -95,5 +100,10 @@ public final class IntRange implements Range, Iterable, JetObj public TypeInfo getTypeInfo() { return typeInfo; } + + @Override + public JetObject getOuterObject() { + return null; + } } } diff --git a/stdlib/src/jet/JetObject.java b/stdlib/src/jet/JetObject.java index c06fd1f755a..96f17a323b6 100644 --- a/stdlib/src/jet/JetObject.java +++ b/stdlib/src/jet/JetObject.java @@ -4,7 +4,9 @@ import jet.typeinfo.TypeInfo; /** * @author abreslav + * @author alex.tkachman */ public interface JetObject { TypeInfo getTypeInfo(); + JetObject getOuterObject(); } diff --git a/stdlib/src/jet/LongRange.java b/stdlib/src/jet/LongRange.java index e0a358599fb..ed94c76cb31 100644 --- a/stdlib/src/jet/LongRange.java +++ b/stdlib/src/jet/LongRange.java @@ -48,6 +48,11 @@ public final class LongRange implements Range, Iterable, JetObject { return typeInfo; } + @Override + public JetObject getOuterObject() { + return null; + } + public static IntRange count(int length) { return new IntRange(0, length); } @@ -95,5 +100,10 @@ public final class LongRange implements Range, Iterable, JetObject { public TypeInfo getTypeInfo() { return typeInfo; } + + @Override + public JetObject getOuterObject() { + return null; + } } } diff --git a/stdlib/src/jet/Tuple0.java b/stdlib/src/jet/Tuple0.java index 34d12022230..a4823e1dd5e 100644 --- a/stdlib/src/jet/Tuple0.java +++ b/stdlib/src/jet/Tuple0.java @@ -31,4 +31,9 @@ public class Tuple0 implements JetObject { public TypeInfo getTypeInfo() { return typeInfo; } + + @Override + public JetObject getOuterObject() { + return null; + } } \ No newline at end of file diff --git a/stdlib/src/jet/runtime/ArrayIterator.java b/stdlib/src/jet/runtime/ArrayIterator.java index 55d4e0a9cd9..7626820a6b6 100644 --- a/stdlib/src/jet/runtime/ArrayIterator.java +++ b/stdlib/src/jet/runtime/ArrayIterator.java @@ -39,6 +39,11 @@ public abstract class ArrayIterator implements Iterator, JetObject { public TypeInfo getTypeInfo() { return TypeInfo.getTypeInfo(GenericIterator.class, false, null, new TypeInfoProjection[] {(TypeInfoProjection) elementTypeInfo}); } + + @Override + public JetObject getOuterObject() { + return null; + } } public static Iterator iterator(T[] array, TypeInfo elementTypeInfo) { @@ -69,6 +74,11 @@ public abstract class ArrayIterator implements Iterator, JetObject { public TypeInfo getTypeInfo() { return typeInfo; } + + @Override + public JetObject getOuterObject() { + return null; + } } public static ByteIterator iterator(byte[] array) { @@ -99,6 +109,11 @@ public abstract class ArrayIterator implements Iterator, JetObject { public TypeInfo getTypeInfo() { return typeInfo; } + + @Override + public JetObject getOuterObject() { + return null; + } } public static ShortIterator iterator(short[] array) { @@ -129,6 +144,11 @@ public abstract class ArrayIterator implements Iterator, JetObject { public TypeInfo getTypeInfo() { return typeInfo; } + + @Override + public JetObject getOuterObject() { + return null; + } } public static IntIterator iterator(int[] array) { @@ -159,6 +179,11 @@ public abstract class ArrayIterator implements Iterator, JetObject { public TypeInfo getTypeInfo() { return typeInfo; } + + @Override + public JetObject getOuterObject() { + return null; + } } public static LongIterator iterator(long[] array) { @@ -189,6 +214,11 @@ public abstract class ArrayIterator implements Iterator, JetObject { public TypeInfo getTypeInfo() { return typeInfo; } + + @Override + public JetObject getOuterObject() { + return null; + } } public static FloatIterator iterator(float[] array) { @@ -219,6 +249,11 @@ public abstract class ArrayIterator implements Iterator, JetObject { public TypeInfo getTypeInfo() { return typeInfo; } + + @Override + public JetObject getOuterObject() { + return null; + } } public static DoubleIterator iterator(double[] array) { @@ -249,6 +284,11 @@ public abstract class ArrayIterator implements Iterator, JetObject { public TypeInfo getTypeInfo() { return typeInfo; } + + @Override + public JetObject getOuterObject() { + return null; + } } public static CharIterator iterator(char[] array) { @@ -279,6 +319,11 @@ public abstract class ArrayIterator implements Iterator, JetObject { public TypeInfo getTypeInfo() { return typeInfo; } + + @Override + public JetObject getOuterObject() { + return null; + } } public static BooleanIterator iterator(boolean[] array) { diff --git a/stdlib/src/jet/typeinfo/TypeInfo.java b/stdlib/src/jet/typeinfo/TypeInfo.java index 2fb20baa47e..32db06ff044 100644 --- a/stdlib/src/jet/typeinfo/TypeInfo.java +++ b/stdlib/src/jet/typeinfo/TypeInfo.java @@ -181,6 +181,11 @@ public abstract class TypeInfo implements JetObject { throw new UnsupportedOperationException("Abstract TypeInfo"); } + @Override + public JetObject getOuterObject() { + return null; + } + @Override public String toString() { return "T:" + signature.klazz.getName() + ":" + varIndex; @@ -388,6 +393,11 @@ public abstract class TypeInfo implements JetObject { return typeInfo; } + @Override + public JetObject getOuterObject() { + return null; + } + public final boolean isSubtypeOf(TypeInfoImpl superType) { if (nullable && !superType.nullable) { return false;