From 232ab0b065351bb9543d0f2c959f6e90d9c679c9 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Tue, 23 Sep 2014 15:01:43 +0400 Subject: [PATCH] Refactor when by enum switch codegen Invoke getAsmType() later, not in the process of annotating the file --- .../org/jetbrains/jet/codegen/AsmUtil.java | 5 -- .../binding/CodegenAnnotatingVisitor.java | 84 ++++++++----------- .../jet/codegen/when/EnumSwitchCodegen.java | 13 +-- .../MappingClassesForWhenByEnumCodegen.java | 50 +++-------- .../jet/codegen/when/WhenByEnumsMapping.java | 22 +++-- 5 files changed, 66 insertions(+), 108 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/AsmUtil.java b/compiler/backend/src/org/jetbrains/jet/codegen/AsmUtil.java index 12e058b5d8a..8f737e6b5fb 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/AsmUtil.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/AsmUtil.java @@ -803,11 +803,6 @@ public class AsmUtil { } } - @NotNull - public static Type getArrayOf(@NotNull String internalClassName) { - return Type.getType("[L" + internalClassName + ";"); - } - public static int getReceiverIndex(@NotNull CodegenContext context, @NotNull CallableMemberDescriptor descriptor) { OwnerKind kind = context.getContextKind(); //Trait always should have this descriptor diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/binding/CodegenAnnotatingVisitor.java b/compiler/backend/src/org/jetbrains/jet/codegen/binding/CodegenAnnotatingVisitor.java index 4b76d0abe50..93ac994f757 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/binding/CodegenAnnotatingVisitor.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/binding/CodegenAnnotatingVisitor.java @@ -500,60 +500,50 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid { @Override public void visitWhenExpression(@NotNull JetWhenExpression expression) { super.visitWhenExpression(expression); - if (isWhenWithEnums(expression)) { - String currentClassName = getCurrentTopLevelClassOrPackagePartInternalName(expression.getContainingJetFile()); + if (!isWhenWithEnums(expression)) return; - if (bindingContext.get(MAPPINGS_FOR_WHENS_BY_ENUM_IN_CLASS_FILE, currentClassName) == null) { - bindingTrace.record( - MAPPINGS_FOR_WHENS_BY_ENUM_IN_CLASS_FILE, - currentClassName, - new ArrayList() - ); - } + String currentClassName = getCurrentTopLevelClassOrPackagePartInternalName(expression.getContainingJetFile()); - List mappings = bindingContext.get(MAPPINGS_FOR_WHENS_BY_ENUM_IN_CLASS_FILE, currentClassName); - assert mappings != null : "guaranteed by contract"; - - int fieldNumber = mappings.size(); - - JetType type = bindingContext.get(BindingContext.EXPRESSION_TYPE, expression.getSubjectExpression()); - assert type != null : "should not be null in a valid when by enums"; - ClassDescriptor classDescriptor = (ClassDescriptor) type.getConstructor().getDeclarationDescriptor(); - assert classDescriptor != null : "because it's enum"; - - WhenByEnumsMapping mapping = new WhenByEnumsMapping( - CodegenBinding.getAsmType(bindingContext, classDescriptor).getInternalName(), - currentClassName, - fieldNumber - ); - - for (CompileTimeConstant constant : SwitchCodegenUtil.getAllConstants(expression, bindingContext)) { - if (constant instanceof NullValue) continue; - - assert constant instanceof EnumValue : "expression in when should be EnumValue"; - mapping.putFirstTime((EnumValue) constant, mapping.size() + 1); - } - - mappings.add(mapping); - - bindingTrace.record(MAPPING_FOR_WHEN_BY_ENUM, expression, mapping); + if (bindingContext.get(MAPPINGS_FOR_WHENS_BY_ENUM_IN_CLASS_FILE, currentClassName) == null) { + bindingTrace.record(MAPPINGS_FOR_WHENS_BY_ENUM_IN_CLASS_FILE, currentClassName, new ArrayList(1)); } + + List mappings = bindingContext.get(MAPPINGS_FOR_WHENS_BY_ENUM_IN_CLASS_FILE, currentClassName); + assert mappings != null : "guaranteed by contract"; + + int fieldNumber = mappings.size(); + + JetType type = bindingContext.get(BindingContext.EXPRESSION_TYPE, expression.getSubjectExpression()); + assert type != null : "should not be null in a valid when by enums"; + ClassDescriptor classDescriptor = (ClassDescriptor) type.getConstructor().getDeclarationDescriptor(); + assert classDescriptor != null : "because it's enum"; + + WhenByEnumsMapping mapping = new WhenByEnumsMapping(classDescriptor, currentClassName, fieldNumber); + + for (CompileTimeConstant constant : SwitchCodegenUtil.getAllConstants(expression, bindingContext)) { + if (constant instanceof NullValue) continue; + + assert constant instanceof EnumValue : "expression in when should be EnumValue"; + mapping.putFirstTime((EnumValue) constant, mapping.size() + 1); + } + + mappings.add(mapping); + + bindingTrace.record(MAPPING_FOR_WHEN_BY_ENUM, expression, mapping); } private boolean isWhenWithEnums(@NotNull JetWhenExpression expression) { return WhenChecker.isWhenByEnum(expression, bindingContext) && - SwitchCodegenUtil.checkAllItemsAreConstantsSatisfying( - expression, - bindingContext, - new Function1() { - @Override - public Boolean invoke( - @NotNull CompileTimeConstant constant - ) { - return constant instanceof EnumValue || constant instanceof NullValue; - } - } - ); + SwitchCodegenUtil.checkAllItemsAreConstantsSatisfying( + expression, + bindingContext, + new Function1() { + @Override + public Boolean invoke(@NotNull CompileTimeConstant constant) { + return constant instanceof EnumValue || constant instanceof NullValue; + } + } + ); } @NotNull diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/when/EnumSwitchCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/when/EnumSwitchCodegen.java index 529da99f523..b12c195edad 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/when/EnumSwitchCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/when/EnumSwitchCodegen.java @@ -52,20 +52,13 @@ public class EnumSwitchCodegen extends SwitchCodegen { v.swap(); - v.invokevirtual( - mapping.getEnumClassInternalName(), - "ordinal", - Type.getMethodDescriptor(Type.INT_TYPE), - false - ); + Type enumType = codegen.getState().getTypeMapper().mapClass(mapping.getEnumClassDescriptor()); + v.invokevirtual(enumType.getInternalName(), "ordinal", Type.getMethodDescriptor(Type.INT_TYPE), false); v.aload(Type.INT_TYPE); } @Override - protected void processConstant( - @NotNull CompileTimeConstant constant, - @NotNull Label entryLabel - ) { + protected void processConstant(@NotNull CompileTimeConstant constant, @NotNull Label entryLabel) { assert constant instanceof EnumValue : "guaranteed by usage contract"; putTransitionOnce(mapping.getIndexByEntry((EnumValue) constant), entryLabel); } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/when/MappingClassesForWhenByEnumCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/when/MappingClassesForWhenByEnumCodegen.java index df6c375a6ae..87f4db3d555 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/when/MappingClassesForWhenByEnumCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/when/MappingClassesForWhenByEnumCodegen.java @@ -18,11 +18,9 @@ package org.jetbrains.jet.codegen.when; import com.intellij.util.ArrayUtil; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.codegen.AsmUtil; import org.jetbrains.jet.codegen.ClassBuilder; import org.jetbrains.jet.codegen.state.GenerationState; import org.jetbrains.jet.lang.psi.JetFile; -import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.constants.EnumValue; import org.jetbrains.jet.lang.resolve.java.diagnostics.JvmDeclarationOrigin; import org.jetbrains.org.objectweb.asm.MethodVisitor; @@ -43,16 +41,8 @@ public class MappingClassesForWhenByEnumCodegen { this.state = state; } - public void generate( - @NotNull List mappings, - @NotNull Type mappingsClass, - @NotNull JetFile srcFile - ) { - ClassBuilder cb = state.getFactory().newVisitor( - JvmDeclarationOrigin.NO_ORIGIN, - mappingsClass, - srcFile - ); + public void generate(@NotNull List mappings, @NotNull Type mappingsClass, @NotNull JetFile srcFile) { + ClassBuilder cb = state.getFactory().newVisitor(JvmDeclarationOrigin.NO_ORIGIN, mappingsClass, srcFile); cb.defineClass( srcFile, V1_6, @@ -69,10 +59,7 @@ public class MappingClassesForWhenByEnumCodegen { cb.done(); } - private static void generateFields( - @NotNull ClassBuilder cb, - @NotNull List mappings - ) { + private static void generateFields(@NotNull ClassBuilder cb, @NotNull List mappings) { for (WhenByEnumsMapping mapping : mappings) { cb.newField( JvmDeclarationOrigin.NO_ORIGIN, @@ -84,10 +71,7 @@ public class MappingClassesForWhenByEnumCodegen { } } - private static void generateInitialization( - @NotNull ClassBuilder cb, - @NotNull List mappings - ) { + private void generateInitialization(@NotNull ClassBuilder cb, @NotNull List mappings) { MethodVisitor mv = cb.newMethod( JvmDeclarationOrigin.NO_ORIGIN, ACC_STATIC | ACC_SYNTHETIC, "", "()V", null, ArrayUtil.EMPTY_STRING_ARRAY @@ -107,40 +91,26 @@ public class MappingClassesForWhenByEnumCodegen { mv.visitEnd(); } - private static void generateInitializationForMapping( + private void generateInitializationForMapping( @NotNull ClassBuilder cb, @NotNull InstructionAdapter v, @NotNull WhenByEnumsMapping mapping ) { - v.invokestatic( - mapping.getEnumClassInternalName(), "values", - Type.getMethodDescriptor( - AsmUtil.getArrayOf(mapping.getEnumClassInternalName()) - ), - false - ); + Type enumType = state.getTypeMapper().mapClass(mapping.getEnumClassDescriptor()); + + v.invokestatic(enumType.getInternalName(), "values", Type.getMethodDescriptor(Type.getType("[" + enumType.getDescriptor())), false); v.arraylength(); v.newarray(Type.INT_TYPE); v.putstatic(cb.getThisName(), mapping.getFieldName(), MAPPINGS_FIELD_DESCRIPTOR); - String enumClassDesc = Type.getObjectType(mapping.getEnumClassInternalName()).getDescriptor(); - for (Map.Entry item : mapping.enumValuesToIntMapping()) { EnumValue enumEntry = item.getKey(); int mappedValue = item.getValue(); v.getstatic(cb.getThisName(), mapping.getFieldName(), MAPPINGS_FIELD_DESCRIPTOR); - v.getstatic( - mapping.getEnumClassInternalName(), - enumEntry.getValue().getName().asString(), - enumClassDesc - ); - v.invokevirtual( - mapping.getEnumClassInternalName(), "ordinal", - Type.getMethodDescriptor(Type.INT_TYPE), - false - ); + v.getstatic(enumType.getInternalName(), enumEntry.getValue().getName().asString(), enumType.getDescriptor()); + v.invokevirtual(enumType.getInternalName(), "ordinal", Type.getMethodDescriptor(Type.INT_TYPE), false); v.iconst(mappedValue); v.astore(Type.INT_TYPE); } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/when/WhenByEnumsMapping.java b/compiler/backend/src/org/jetbrains/jet/codegen/when/WhenByEnumsMapping.java index 60b29ba0664..6f51b0c582c 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/when/WhenByEnumsMapping.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/when/WhenByEnumsMapping.java @@ -17,6 +17,7 @@ package org.jetbrains.jet.codegen.when; import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.resolve.constants.EnumValue; import java.util.HashMap; @@ -27,13 +28,17 @@ public class WhenByEnumsMapping { private static final String MAPPINGS_CLASS_NAME_POSTFIX = "$WhenMappings"; private final Map map = new HashMap(); - private final String enumClassInternalName; + private final ClassDescriptor enumClassDescriptor; private final String outerClassInternalNameForExpression; private final String mappingsClassInternalName; private final int fieldNumber; - public WhenByEnumsMapping(String enumClassInternalName, String outerClassInternalNameForExpression, int fieldNumber) { - this.enumClassInternalName = enumClassInternalName; + public WhenByEnumsMapping( + @NotNull ClassDescriptor enumClassDescriptor, + @NotNull String outerClassInternalNameForExpression, + int fieldNumber + ) { + this.enumClassDescriptor = enumClassDescriptor; this.outerClassInternalNameForExpression = outerClassInternalNameForExpression; this.mappingsClassInternalName = outerClassInternalNameForExpression + MAPPINGS_CLASS_NAME_POSTFIX; this.fieldNumber = fieldNumber; @@ -45,7 +50,7 @@ public class WhenByEnumsMapping { return result; } - public void putFirstTime(EnumValue value, int index) { + public void putFirstTime(@NotNull EnumValue value, int index) { if (!map.containsKey(value)) { map.put(value, index); } @@ -55,22 +60,27 @@ public class WhenByEnumsMapping { return map.size(); } + @NotNull public String getFieldName() { return MAPPING_ARRAY_FIELD_PREFIX + fieldNumber; } - public String getEnumClassInternalName() { - return enumClassInternalName; + @NotNull + public ClassDescriptor getEnumClassDescriptor() { + return enumClassDescriptor; } + @NotNull public String getOuterClassInternalNameForExpression() { return outerClassInternalNameForExpression; } + @NotNull public String getMappingsClassInternalName() { return mappingsClassInternalName; } + @NotNull public Iterable> enumValuesToIntMapping() { return map.entrySet(); }