diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContexts.java b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContexts.java index 03aa14cadc5..ace432563b9 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContexts.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContexts.java @@ -217,7 +217,7 @@ public class CodegenContexts { final Type type = enclosingClassType(typeMapper); outerExpression = type != null - ? StackValue.field(type, typeMapper.getClassFQName(contextDescriptor), "this$0", false) + ? StackValue.field(type, typeMapper.getJvmClassName(contextDescriptor), "this$0", false) : null; } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java index 2eb6a38442b..2fadffc9075 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java @@ -83,11 +83,78 @@ public class JetTypeMapper { public static final Type TYPE_FUNCTION0 = Type.getObjectType("jet/Function0"); public static final Type TYPE_FUNCTION1 = Type.getObjectType("jet/Function1"); + public static class SpecialTypes { + private static final class SpecialTypeKey { + @NotNull + private final FqNameUnsafe className; + private final boolean nullable; + + private SpecialTypeKey(@NotNull FqNameUnsafe className, boolean nullable) { + this.className = className; + this.nullable = nullable; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + SpecialTypeKey that = (SpecialTypeKey) o; + + if (nullable != that.nullable) return false; + if (!className.equals(that.className)) return false; + + return true; + } + + @Override + public int hashCode() { + int result = className.hashCode(); + result = 31 * result + (nullable ? 1 : 0); + return result; + } + } + + private final Map asmTypes = Maps.newHashMap(); + + @Nullable + public Type get(@NotNull JetType type) { + ClassifierDescriptor classifier = type.getConstructor().getDeclarationDescriptor(); + return asmTypes.get(new SpecialTypeKey(DescriptorUtils.getFQName(classifier), type.isNullable())); + } + + private void register(@NotNull ClassName className, @NotNull Type nonNullType, @NotNull Type nullableType) { + asmTypes.put(new SpecialTypeKey(className.getFqName().toUnsafe(), true), nullableType); + asmTypes.put(new SpecialTypeKey(className.getFqName().toUnsafe(), false), nonNullType); + } + + public void init() { + register(JetStandardLibraryNames.NOTHING, TYPE_NOTHING, TYPE_NOTHING); + + for (JvmPrimitiveType jvmPrimitiveType : JvmPrimitiveType.values()) { + PrimitiveType primitiveType = jvmPrimitiveType.getPrimitiveType(); + register(primitiveType.getClassName(), jvmPrimitiveType.getAsmType(), jvmPrimitiveType.getWrapper().getAsmType()); + } + + register(JetStandardLibraryNames.NUMBER, JL_NUMBER_TYPE, JL_NUMBER_TYPE); + register(JetStandardLibraryNames.STRING, JL_STRING_TYPE, JL_STRING_TYPE); + register(JetStandardLibraryNames.CHAR_SEQUENCE, JL_CHAR_SEQUENCE_TYPE, JL_CHAR_SEQUENCE_TYPE); + register(JetStandardLibraryNames.THROWABLE, TYPE_THROWABLE, TYPE_THROWABLE); + register(JetStandardLibraryNames.COMPARABLE, JL_COMPARABLE_TYPE, JL_COMPARABLE_TYPE); + + for (JvmPrimitiveType jvmPrimitiveType : JvmPrimitiveType.values()) { + PrimitiveType primitiveType = jvmPrimitiveType.getPrimitiveType(); + register(primitiveType.getArrayClassName(), jvmPrimitiveType.getAsmArrayType(), jvmPrimitiveType.getAsmArrayType()); + } + } + } + + public BindingContext bindingContext; private ClosureAnnotator closureAnnotator; private boolean mapBuiltinsToJava; private ClassBuilderMode classBuilderMode; - + private final SpecialTypes specialTypes = new SpecialTypes(); @Inject public void setBindingContext(BindingContext bindingContext) { @@ -111,12 +178,9 @@ public class JetTypeMapper { @PostConstruct public void init() { - initKnownTypes(); + specialTypes.init(); } - - - public boolean hasThis0(ClassDescriptor classDescriptor) { return closureAnnotator.hasThis0(classDescriptor); } @@ -125,40 +189,6 @@ public class JetTypeMapper { return closureAnnotator; } - private static final class KnownTypeKey { - @NotNull - private final FqNameUnsafe className; - private final boolean nullable; - - private KnownTypeKey(@NotNull FqNameUnsafe className, boolean nullable) { - this.className = className; - this.nullable = nullable; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - KnownTypeKey that = (KnownTypeKey) o; - - if (nullable != that.nullable) return false; - if (!className.equals(that.className)) return false; - - return true; - } - - @Override - public int hashCode() { - int result = className.hashCode(); - result = 31 * result + (nullable ? 1 : 0); - return result; - } - } - - private final HashMap knowTypes = Maps.newHashMap(); - - public static boolean isIntPrimitive(Type type) { return type == Type.INT_TYPE || type == Type.SHORT_TYPE || type == Type.BYTE_TYPE || type == Type.CHAR_TYPE; } @@ -308,17 +338,12 @@ public class JetTypeMapper { return null; } - public JvmClassName getClassFQName(ClassDescriptor classDescriptor) { - return JvmClassName.byInternalName(getFQName(classDescriptor)); + public JvmClassName getJvmClassName(ClassDescriptor classDescriptor) { + return JvmClassName.byInternalName(getJvmInternalFQName(classDescriptor)); } - /** - * @return Internal name - * - * @see DescriptorUtils#getFQName(DeclarationDescriptor) - */ @NotNull - private String getFQName(@NotNull DeclarationDescriptor descriptor) { + private String getJvmInternalFQName(@NotNull DeclarationDescriptor descriptor) { descriptor = descriptor.getOriginal(); if (descriptor instanceof FunctionDescriptor) { @@ -339,15 +364,15 @@ public class JetTypeMapper { if (klass.getContainingDeclaration() instanceof ClassDescriptor) { ClassDescriptor containingKlass = (ClassDescriptor) klass.getContainingDeclaration(); if (containingKlass.getKind() == ClassKind.ENUM_CLASS) { - return getFQName(containingKlass); + return getJvmInternalFQName(containingKlass); } else { - return getFQName(containingKlass) + JvmAbi.CLASS_OBJECT_SUFFIX; + return getJvmInternalFQName(containingKlass) + JvmAbi.CLASS_OBJECT_SUFFIX; } } } else if (klass.getKind() == ClassKind.ENUM_ENTRY) { - return getFQName(klass.getContainingDeclaration()); + return getJvmInternalFQName(klass.getContainingDeclaration()); } } @@ -365,7 +390,7 @@ public class JetTypeMapper { return className.getInternalName(); } - String baseName = getFQName(container); + String baseName = getJvmInternalFQName(container); if (!baseName.isEmpty()) { return baseName + (container instanceof NamespaceDescriptor ? "/" : "$") + name.getIdentifier(); } @@ -385,17 +410,16 @@ public class JetTypeMapper { if (mapBuiltinsToJava) { if (classifier instanceof ClassDescriptor) { - KnownTypeKey key = new KnownTypeKey(DescriptorUtils.getFQName(classifier), jetType.isNullable()); - known = knowTypes.get(key); + known = specialTypes.get(jetType); } } if (known != null) { if (kind == MapTypeMode.VALUE) { - return mapKnownAsmType(jetType, known, signatureVisitor, false); + return mapKnownAsmType(jetType, known, signatureVisitor); } else if (kind == MapTypeMode.TYPE_PARAMETER) { - return mapKnownAsmType(jetType, known, signatureVisitor, true); + return mapKnownAsmType(jetType, boxType(known), signatureVisitor); } else if (kind == MapTypeMode.TRAIT_IMPL) { throw new IllegalStateException("TRAIT_IMPL is not possible for " + jetType); @@ -428,7 +452,7 @@ public class JetTypeMapper { } Type asmType = Type.getObjectType("error/NonExistentClass"); if (signatureVisitor != null) { - visitAsmType(signatureVisitor, asmType, true); + writeSimpleType(signatureVisitor, asmType, true); } checkValidType(asmType); return asmType; @@ -461,7 +485,7 @@ public class JetTypeMapper { if (JetStandardClasses.getAny().equals(descriptor)) { if (signatureVisitor != null) { - visitAsmType(signatureVisitor, TYPE_OBJECT, jetType.isNullable()); + writeSimpleType(signatureVisitor, TYPE_OBJECT, jetType.isNullable()); } checkValidType(TYPE_OBJECT); return TYPE_OBJECT; @@ -469,33 +493,12 @@ public class JetTypeMapper { if (descriptor instanceof ClassDescriptor) { - Type asmType; - boolean forceReal; - if (JetStandardLibraryNames.COMPARABLE.is((ClassDescriptor) descriptor) && mapBuiltinsToJava) { - if (jetType.getArguments().size() != 1) { - throw new UnsupportedOperationException("Comparable must have one type argument"); - } + JvmClassName name = getJvmClassName((ClassDescriptor) descriptor); + Type asmType = Type.getObjectType(name.getInternalName() + (kind == MapTypeMode.TRAIT_IMPL ? JvmAbi.TRAIT_IMPL_SUFFIX : "")); + boolean forceReal = isForceReal(name); - asmType = JL_COMPARABLE_TYPE; - forceReal = false; - } - else { - JvmClassName name = getClassFQName((ClassDescriptor) descriptor); - asmType = Type.getObjectType(name.getInternalName() + (kind == MapTypeMode.TRAIT_IMPL ? JvmAbi.TRAIT_IMPL_SUFFIX : "")); - forceReal = isForceReal(name); - } - - if (signatureVisitor != null) { - signatureVisitor.writeClassBegin(asmType.getInternalName(), jetType.isNullable(), forceReal); - for (TypeProjection proj : jetType.getArguments()) { - // TODO: +- - signatureVisitor.writeTypeArgument(proj.getProjectionKind()); - mapType(proj.getType(), signatureVisitor, MapTypeMode.TYPE_PARAMETER); - signatureVisitor.writeTypeArgumentEnd(); - } - signatureVisitor.writeClassEnd(); - } + writeGenericType(jetType, signatureVisitor, asmType, forceReal); checkValidType(asmType); return asmType; @@ -515,26 +518,34 @@ public class JetTypeMapper { throw new UnsupportedOperationException("Unknown type " + jetType); } - - private Type mapKnownAsmType(JetType jetType, Type asmType, @Nullable BothSignatureWriter signatureVisitor, boolean boxPrimitive) { - if (boxPrimitive) { - Type boxed = boxType(asmType); - if (signatureVisitor != null) { - visitAsmType(signatureVisitor, boxed, jetType.isNullable()); + + private void writeGenericType(JetType jetType, BothSignatureWriter signatureVisitor, Type asmType, boolean forceReal) { + if (signatureVisitor != null) { + signatureVisitor.writeClassBegin(asmType.getInternalName(), jetType.isNullable(), forceReal); + for (TypeProjection proj : jetType.getArguments()) { + // TODO: +- + signatureVisitor.writeTypeArgument(proj.getProjectionKind()); + mapType(proj.getType(), signatureVisitor, MapTypeMode.TYPE_PARAMETER); + signatureVisitor.writeTypeArgumentEnd(); } - checkValidType(boxed); - return boxed; - } - else { - if (signatureVisitor != null) { - visitAsmType(signatureVisitor, asmType, jetType.isNullable()); - } - checkValidType(asmType); - return asmType; + signatureVisitor.writeClassEnd(); } } - public static void visitAsmType(BothSignatureWriter visitor, Type asmType, boolean nullable) { + private Type mapKnownAsmType(JetType jetType, Type asmType, @Nullable BothSignatureWriter signatureVisitor) { + if (signatureVisitor != null) { + if (jetType.getArguments().isEmpty()) { + writeSimpleType(signatureVisitor, asmType, jetType.isNullable()); + } + else { + writeGenericType(jetType, signatureVisitor, asmType, false); + } + } + checkValidType(asmType); + return asmType; + } + + public static void writeSimpleType(BothSignatureWriter visitor, Type asmType, boolean nullable) { visitor.writeAsmType(asmType, nullable); } @@ -1029,30 +1040,6 @@ public class JetTypeMapper { return result; } - private void registerKnownType(@NotNull ClassName className, @NotNull Type nonNullType, @NotNull Type nullableType) { - knowTypes.put(new KnownTypeKey(className.getFqName().toUnsafe(), true), nullableType); - knowTypes.put(new KnownTypeKey(className.getFqName().toUnsafe(), false), nonNullType); - } - - private void initKnownTypes() { - registerKnownType(JetStandardLibraryNames.NOTHING, TYPE_NOTHING, TYPE_NOTHING); - - for (JvmPrimitiveType jvmPrimitiveType : JvmPrimitiveType.values()) { - PrimitiveType primitiveType = jvmPrimitiveType.getPrimitiveType(); - registerKnownType(primitiveType.getClassName(), jvmPrimitiveType.getAsmType(), jvmPrimitiveType.getWrapper().getAsmType()); - } - - registerKnownType(JetStandardLibraryNames.NUMBER, JL_NUMBER_TYPE, JL_NUMBER_TYPE); - registerKnownType(JetStandardLibraryNames.STRING, JL_STRING_TYPE, JL_STRING_TYPE); - registerKnownType(JetStandardLibraryNames.CHAR_SEQUENCE, JL_CHAR_SEQUENCE_TYPE, JL_CHAR_SEQUENCE_TYPE); - registerKnownType(JetStandardLibraryNames.THROWABLE, TYPE_THROWABLE, TYPE_THROWABLE); - - for (JvmPrimitiveType jvmPrimitiveType : JvmPrimitiveType.values()) { - PrimitiveType primitiveType = jvmPrimitiveType.getPrimitiveType(); - registerKnownType(primitiveType.getArrayClassName(), jvmPrimitiveType.getAsmArrayType(), jvmPrimitiveType.getAsmArrayType()); - } - } - private static boolean isForceReal(JvmClassName className) { return JvmPrimitiveType.getByWrapperClass(className) != null || className.getFqName().getFqName().equals("java.lang.String")