From 8d8c3d2b9e6d404d73de9b06676f580481f9ee2d Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Thu, 17 Jul 2014 11:59:58 +0400 Subject: [PATCH] When2Switch: generate ifnonnull check for nullable values before *switch-opcode --- .../binding/CodegenAnnotatingVisitor.java | 9 ++-- .../jet/codegen/when/EnumSwitchCodegen.java | 5 +- .../jet/codegen/when/StringSwitchCodegen.java | 3 ++ .../jet/codegen/when/SwitchCodegen.java | 48 +++++++++++++++++-- .../jet/codegen/when/SwitchCodegenUtil.java | 21 +++++--- .../whenEnumOptimization/nullability.kt | 40 ++++++++++++++++ .../whenStringOptimization/nullability.kt | 41 ++++++++++++++++ .../whenEnumOptimization/nullability.kt | 26 ++++++++++ .../whenStringOptimization/nullability.kt | 18 +++++++ .../codegen/BytecodeTextTestGenerated.java | 10 ++++ ...lackBoxWithStdlibCodegenTestGenerated.java | 10 ++++ 11 files changed, 218 insertions(+), 13 deletions(-) create mode 100644 compiler/testData/codegen/boxWithStdlib/whenEnumOptimization/nullability.kt create mode 100644 compiler/testData/codegen/boxWithStdlib/whenStringOptimization/nullability.kt create mode 100644 compiler/testData/codegen/bytecodeText/whenEnumOptimization/nullability.kt create mode 100644 compiler/testData/codegen/bytecodeText/whenStringOptimization/nullability.kt 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 608ce19731b..1ea38075945 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/binding/CodegenAnnotatingVisitor.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/binding/CodegenAnnotatingVisitor.java @@ -40,6 +40,7 @@ import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedValueArgument; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lang.resolve.constants.EnumValue; +import org.jetbrains.jet.lang.resolve.constants.NullValue; import org.jetbrains.jet.lang.resolve.java.JvmAbi; import org.jetbrains.jet.lang.resolve.java.PackageClassUtils; import org.jetbrains.jet.lang.resolve.kotlin.PackagePartClassUtils; @@ -525,6 +526,8 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid { ); 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); } @@ -543,11 +546,11 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid { new Function1() { @Override public Boolean invoke( - @NotNull CompileTimeConstant constant + @NotNull CompileTimeConstant constant ) { - return constant instanceof EnumValue; + return constant instanceof EnumValue || constant instanceof NullValue; } - } + } ); } 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 082f397ed42..ff2241c3913 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/when/EnumSwitchCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/when/EnumSwitchCodegen.java @@ -25,13 +25,16 @@ public class EnumSwitchCodegen extends SwitchCodegen { protected void generateSubject() { codegen.getState().getMappingsClassesForWhenByEnum().generateMappingsClassForExpression(expression); + super.generateSubject(); + generateNullCheckIfNeeded(); + v.getstatic( mapping.getMappingsClassInternalName(), mapping.getFieldName(), MappingClassesForWhenByEnumCodegen.MAPPINGS_FIELD_DESCRIPTOR ); - super.generateSubject(); + v.swap(); v.invokevirtual( mapping.getEnumClassInternalName(), diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/when/StringSwitchCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/when/StringSwitchCodegen.java index db5b334c104..78324811957 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/when/StringSwitchCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/when/StringSwitchCodegen.java @@ -75,6 +75,9 @@ public class StringSwitchCodegen extends SwitchCodegen { v.store(tempVarIndex, subjectType); v.load(tempVarIndex, subjectType); + + generateNullCheckIfNeeded(); + v.invokevirtual( subjectType.getInternalName(), "hashCode", HASH_CODE_METHOD_DESC, false diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/when/SwitchCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/when/SwitchCodegen.java index d4ffa1158b9..9040a091e8d 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/when/SwitchCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/when/SwitchCodegen.java @@ -23,12 +23,16 @@ import org.jetbrains.jet.lang.psi.JetWhenEntry; import org.jetbrains.jet.lang.psi.JetWhenExpression; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; +import org.jetbrains.jet.lang.resolve.constants.NullValue; +import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.org.objectweb.asm.Label; import org.jetbrains.org.objectweb.asm.Type; import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter; import java.util.*; +import static org.jetbrains.jet.lang.resolve.BindingContext.EXPRESSION_TYPE; + abstract public class SwitchCodegen { protected final JetWhenExpression expression; protected final boolean isStatement; @@ -39,7 +43,7 @@ abstract public class SwitchCodegen { protected final InstructionAdapter v; protected final NavigableMap transitionsTable = new TreeMap(); - protected final Collection