When by String constants:
Generate TABLESWITCH/LOOKUPSWITCH bytecode operation for when operator by String constants
This commit is contained in:
committed by
Evgeny Gerashchenko
parent
5a1c995b5c
commit
d4cb822ee8
@@ -37,6 +37,7 @@ import org.jetbrains.jet.codegen.inline.NameGenerator;
|
||||
import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethod;
|
||||
import org.jetbrains.jet.codegen.state.GenerationState;
|
||||
import org.jetbrains.jet.codegen.state.JetTypeMapper;
|
||||
import org.jetbrains.jet.codegen.when.SwitchCodegen;
|
||||
import org.jetbrains.jet.codegen.when.SwitchCodegenUtil;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils;
|
||||
@@ -112,7 +113,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
* When we create a temporary variable to hold some value not to compute it many times
|
||||
* we put it into this map to emit access to that variable instead of evaluating the whole expression
|
||||
*/
|
||||
final Map<JetElement, StackValue> tempVariables = Maps.newHashMap();
|
||||
public final Map<JetElement, StackValue> tempVariables = Maps.newHashMap();
|
||||
|
||||
private int myLastLineNumber = -1;
|
||||
|
||||
@@ -3725,8 +3726,10 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
|
||||
Type resultType = isStatement ? Type.VOID_TYPE : expressionType(expression);
|
||||
|
||||
if (SwitchCodegenUtil.canSwitchBeUsedIn(expression, subjectType, bindingContext)) {
|
||||
return generateSwitch(expression, resultType, isStatement);
|
||||
SwitchCodegen switchCodegen = SwitchCodegenUtil.buildAppropriateSwitchCodegenIfPossible(expression, isStatement, this);
|
||||
if (switchCodegen != null) {
|
||||
switchCodegen.generate();
|
||||
return StackValue.onStack(resultType);
|
||||
}
|
||||
|
||||
int subjectLocal = expr != null ? myFrameMap.enterTemp(subjectType) : -1;
|
||||
@@ -3816,19 +3819,6 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
}
|
||||
}
|
||||
|
||||
private StackValue generateSwitch(
|
||||
@NotNull JetWhenExpression expression,
|
||||
@NotNull Type resultType,
|
||||
boolean isStatement
|
||||
) {
|
||||
SwitchCodegenUtil.buildAppropriateSwitchCodegen(
|
||||
expression, isStatement, this
|
||||
|
||||
).generate();
|
||||
|
||||
return StackValue.onStack(resultType);
|
||||
}
|
||||
|
||||
private boolean isIntRangeExpr(JetExpression rangeExpression) {
|
||||
if (rangeExpression instanceof JetBinaryExpression) {
|
||||
JetBinaryExpression binaryExpression = (JetBinaryExpression) rangeExpression;
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright 2010-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.jet.codegen.when;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.codegen.ExpressionCodegen;
|
||||
import org.jetbrains.jet.lang.psi.JetWhenExpression;
|
||||
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
||||
import org.jetbrains.jet.lang.resolve.constants.StringValue;
|
||||
import org.jetbrains.org.objectweb.asm.Label;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class StringSwitchCodegen extends SwitchCodegen {
|
||||
private static final String HASH_CODE_METHOD_DESC = Type.getMethodDescriptor(Type.INT_TYPE);
|
||||
private static final String EQUALS_METHOD_DESC = Type.getMethodDescriptor(Type.BOOLEAN_TYPE, Type.getType(Object.class));
|
||||
|
||||
private final Map<Integer, List<Pair<String, Label>>> hashCodesToStringAndEntryLabel = Maps.newHashMap();
|
||||
private int tempVarIndex;
|
||||
|
||||
public StringSwitchCodegen(
|
||||
@NotNull JetWhenExpression expression,
|
||||
boolean isStatement,
|
||||
@NotNull ExpressionCodegen codegen
|
||||
) {
|
||||
super(expression, isStatement, codegen);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processConstant(
|
||||
@NotNull CompileTimeConstant constant, @NotNull Label entryLabel
|
||||
) {
|
||||
assert constant instanceof StringValue : "guaranteed by usage contract";
|
||||
int hashCode = constant.hashCode();
|
||||
|
||||
if (!transitionsTable.containsKey(hashCode)) {
|
||||
transitionsTable.put(hashCode, new Label());
|
||||
hashCodesToStringAndEntryLabel.put(hashCode, new ArrayList<Pair<String, Label>>());
|
||||
}
|
||||
|
||||
hashCodesToStringAndEntryLabel.get(hashCode).add(
|
||||
new Pair<String, Label>(((StringValue) constant).getValue(), entryLabel)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generate() {
|
||||
super.generate();
|
||||
codegen.myFrameMap.leaveTemp(subjectType);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generateSubject() {
|
||||
tempVarIndex = codegen.myFrameMap.enterTemp(subjectType);
|
||||
super.generateSubject();
|
||||
v.store(tempVarIndex, subjectType);
|
||||
|
||||
v.load(tempVarIndex, subjectType);
|
||||
v.invokevirtual(
|
||||
subjectType.getInternalName(),
|
||||
"hashCode", HASH_CODE_METHOD_DESC, false
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generateEntries() {
|
||||
for (int hashCode : hashCodesToStringAndEntryLabel.keySet()) {
|
||||
v.visitLabel(transitionsTable.get(hashCode));
|
||||
|
||||
List<Pair<String, Label>> items = hashCodesToStringAndEntryLabel.get(hashCode);
|
||||
Label nextLabel = null;
|
||||
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
if (nextLabel != null) {
|
||||
v.visitLabel(nextLabel);
|
||||
}
|
||||
|
||||
Pair<String, Label> stringAndEntryLabel = items.get(i);
|
||||
|
||||
v.load(tempVarIndex, subjectType);
|
||||
v.aconst(stringAndEntryLabel.first);
|
||||
v.invokevirtual(
|
||||
subjectType.getInternalName(),
|
||||
"equals",
|
||||
EQUALS_METHOD_DESC,
|
||||
false
|
||||
);
|
||||
|
||||
if (i + 1 < items.size()) {
|
||||
nextLabel = new Label();
|
||||
}
|
||||
else {
|
||||
nextLabel = defaultLabel;
|
||||
}
|
||||
|
||||
v.ifeq(nextLabel);
|
||||
v.goTo(stringAndEntryLabel.getSecond());
|
||||
}
|
||||
}
|
||||
|
||||
super.generateEntries();
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,8 @@ package org.jetbrains.jet.codegen.when;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.codegen.ExpressionCodegen;
|
||||
import org.jetbrains.jet.codegen.FrameMap;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
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.org.objectweb.asm.Label;
|
||||
@@ -41,6 +42,7 @@ abstract public class SwitchCodegen {
|
||||
protected final Collection<Label> entryLabels = new ArrayList<Label>();
|
||||
protected Label elseLabel = new Label();
|
||||
protected Label endLabel = new Label();
|
||||
protected Label defaultLabel;
|
||||
|
||||
public SwitchCodegen(
|
||||
@NotNull JetWhenExpression expression, boolean isStatement,
|
||||
@@ -52,7 +54,7 @@ abstract public class SwitchCodegen {
|
||||
this.bindingContext = codegen.getBindingContext();
|
||||
|
||||
subjectType = codegen.expressionType(expression.getSubjectExpression());
|
||||
resultType = codegen.expressionType(expression);
|
||||
resultType = isStatement ? Type.VOID_TYPE : codegen.expressionType(expression);
|
||||
v = codegen.v;
|
||||
}
|
||||
|
||||
@@ -66,25 +68,11 @@ abstract public class SwitchCodegen {
|
||||
|
||||
generateSubject();
|
||||
|
||||
generateSwitchInstructionByTransitionsTable(
|
||||
transitionsTable,
|
||||
// if there is no else-entry and it's statement then default --- endLabel
|
||||
(hasElse || !isStatement) ? elseLabel : endLabel
|
||||
);
|
||||
// if there is no else-entry and it's statement then default --- endLabel
|
||||
defaultLabel = (hasElse || !isStatement) ? elseLabel : endLabel;
|
||||
generateSwitchInstructionByTransitionsTable();
|
||||
|
||||
// resolving entries' entryLabels and generating entries' code
|
||||
Iterator<Label> entryLabelsIterator = entryLabels.iterator();
|
||||
for (JetWhenEntry entry : expression.getEntries()) {
|
||||
v.visitLabel(entryLabelsIterator.next());
|
||||
|
||||
FrameMap.Mark mark = codegen.myFrameMap.mark();
|
||||
codegen.gen(entry.getExpression(), resultType);
|
||||
mark.dropTo();
|
||||
|
||||
if (!entry.isElse()) {
|
||||
v.goTo(endLabel);
|
||||
}
|
||||
}
|
||||
generateEntries();
|
||||
|
||||
// there is no else-entry but this is not statement, so we should return Unit
|
||||
if (!hasElse && !isStatement) {
|
||||
@@ -120,7 +108,7 @@ abstract public class SwitchCodegen {
|
||||
@NotNull CompileTimeConstant constant,
|
||||
@NotNull Label entryLabel
|
||||
);
|
||||
|
||||
|
||||
protected void putTransitionOnce(int value, @NotNull Label entryLabel) {
|
||||
if (!transitionsTable.containsKey(value)) {
|
||||
transitionsTable.put(value, entryLabel);
|
||||
@@ -136,14 +124,12 @@ abstract public class SwitchCodegen {
|
||||
codegen.gen(expression.getSubjectExpression(), subjectType);
|
||||
}
|
||||
|
||||
private void generateSwitchInstructionByTransitionsTable(
|
||||
@NotNull Map<Integer, Label> transitions, @NotNull Label defaultLabel
|
||||
) {
|
||||
int[] keys = new int[transitions.size()];
|
||||
Label[] labels = new Label[transitions.size()];
|
||||
private void generateSwitchInstructionByTransitionsTable() {
|
||||
int[] keys = new int[transitionsTable.size()];
|
||||
Label[] labels = new Label[transitionsTable.size()];
|
||||
int i = 0;
|
||||
|
||||
for (Map.Entry<Integer, Label> transition : transitions.entrySet()) {
|
||||
for (Map.Entry<Integer, Label> transition : transitionsTable.entrySet()) {
|
||||
keys[i] = transition.getKey();
|
||||
labels[i] = transition.getValue();
|
||||
|
||||
@@ -181,4 +167,20 @@ abstract public class SwitchCodegen {
|
||||
|
||||
v.tableswitch(lo, hi, defaultLabel, sparseLabels);
|
||||
}
|
||||
|
||||
protected void generateEntries() {
|
||||
// resolving entries' entryLabels and generating entries' code
|
||||
Iterator<Label> entryLabelsIterator = entryLabels.iterator();
|
||||
for (JetWhenEntry entry : expression.getEntries()) {
|
||||
v.visitLabel(entryLabelsIterator.next());
|
||||
|
||||
FrameMap.Mark mark = codegen.myFrameMap.mark();
|
||||
codegen.gen(entry.getExpression(), resultType);
|
||||
mark.dropTo();
|
||||
|
||||
if (!entry.isElse()) {
|
||||
v.goTo(endLabel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,39 +25,13 @@ import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
||||
import org.jetbrains.jet.lang.resolve.constants.IntegerValueConstant;
|
||||
import org.jetbrains.jet.lang.resolve.constants.StringValue;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class SwitchCodegenUtil {
|
||||
public static boolean canSwitchBeUsedIn(
|
||||
@NotNull JetWhenExpression expression,
|
||||
@NotNull Type subjectType,
|
||||
@NotNull BindingContext bindingContext
|
||||
) {
|
||||
// *switch opcode can be used if each item is enum entry or integral constant
|
||||
// in case of enum CodegenAnnotationVisitor should put mappings into bindingContext
|
||||
if (bindingContext.get(CodegenBinding.MAPPING_FOR_WHEN_BY_ENUM, expression) != null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int typeSort = subjectType.getSort();
|
||||
|
||||
if (typeSort != Type.INT && typeSort != Type.CHAR && typeSort != Type.SHORT && typeSort != Type.BYTE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return checkAllItemsAreConstantsSatisfying(expression, bindingContext, new Function1<CompileTimeConstant, Boolean>() {
|
||||
@Override
|
||||
public Boolean invoke(
|
||||
@NotNull CompileTimeConstant constant
|
||||
) {
|
||||
return constant instanceof IntegerValueConstant;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static boolean checkAllItemsAreConstantsSatisfying(
|
||||
@NotNull JetWhenExpression expression,
|
||||
@NotNull BindingContext bindingContext,
|
||||
@@ -121,18 +95,70 @@ public class SwitchCodegenUtil {
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static SwitchCodegen buildAppropriateSwitchCodegen(
|
||||
@Nullable
|
||||
public static SwitchCodegen buildAppropriateSwitchCodegenIfPossible(
|
||||
@NotNull JetWhenExpression expression,
|
||||
boolean isStatement,
|
||||
@NotNull ExpressionCodegen codegen
|
||||
) {
|
||||
Type subjectType = codegen.expressionType(expression.getSubjectExpression());
|
||||
BindingContext bindingContext = codegen.getBindingContext();
|
||||
|
||||
WhenByEnumsMapping mapping = codegen.getBindingContext().get(CodegenBinding.MAPPING_FOR_WHEN_BY_ENUM, expression);
|
||||
|
||||
if (mapping != null) {
|
||||
return new EnumSwitchCodegen(expression, isStatement, codegen, mapping);
|
||||
}
|
||||
|
||||
return new IntegralConstantsSwitchCodegen(expression, isStatement, codegen);
|
||||
if (isIntegralConstantsSwitch(expression, subjectType, bindingContext)) {
|
||||
return new IntegralConstantsSwitchCodegen(expression, isStatement, codegen);
|
||||
}
|
||||
|
||||
if (isStringConstantsSwitch(expression, subjectType, bindingContext)) {
|
||||
return new StringSwitchCodegen(expression, isStatement, codegen);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean isIntegralConstantsSwitch(
|
||||
@NotNull JetWhenExpression expression,
|
||||
@NotNull Type subjectType,
|
||||
@NotNull BindingContext bindingContext
|
||||
) {
|
||||
int typeSort = subjectType.getSort();
|
||||
|
||||
if (typeSort != Type.INT && typeSort != Type.CHAR && typeSort != Type.SHORT && typeSort != Type.BYTE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return checkAllItemsAreConstantsSatisfying(expression, bindingContext, new Function1<CompileTimeConstant, Boolean>() {
|
||||
@Override
|
||||
public Boolean invoke(
|
||||
@NotNull CompileTimeConstant constant
|
||||
) {
|
||||
return constant instanceof IntegerValueConstant;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static boolean isStringConstantsSwitch(
|
||||
@NotNull JetWhenExpression expression,
|
||||
@NotNull Type subjectType,
|
||||
@NotNull BindingContext bindingContext
|
||||
) {
|
||||
|
||||
if (!subjectType.getClassName().equals(String.class.getName())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return checkAllItemsAreConstantsSatisfying(expression, bindingContext, new Function1<CompileTimeConstant, Boolean>() {
|
||||
@Override
|
||||
public Boolean invoke(
|
||||
@NotNull CompileTimeConstant constant
|
||||
) {
|
||||
return constant instanceof StringValue;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
fun foo(x : String) : String {
|
||||
when (x) {
|
||||
"abc" -> return "abc"
|
||||
"efg", "ghi", "abc" -> return "efg_ghi"
|
||||
else -> return "other"
|
||||
}
|
||||
}
|
||||
|
||||
fun box() : String {
|
||||
assertEquals("abc", foo("abc"))
|
||||
assertEquals("efg_ghi", foo("efg"))
|
||||
assertEquals("efg_ghi", foo("ghi"))
|
||||
|
||||
assertEquals("other", foo("xyz"))
|
||||
|
||||
return "OK"
|
||||
}
|
||||
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
fun foo(x : String) : String {
|
||||
assert("abz]".hashCode() == "aby|".hashCode())
|
||||
|
||||
when (x) {
|
||||
"abz]" -> return "abz"
|
||||
"ghi" -> return "ghi"
|
||||
"aby|" -> return "aby"
|
||||
"abz]" -> return "fail"
|
||||
}
|
||||
|
||||
return "other"
|
||||
}
|
||||
|
||||
fun box() : String {
|
||||
assertEquals("abz", foo("abz]"))
|
||||
assertEquals("aby", foo("aby|"))
|
||||
assertEquals("ghi", foo("ghi"))
|
||||
|
||||
assertEquals("other", foo("xyz"))
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
fun foo(x : String) : String {
|
||||
return when (x) {
|
||||
"abc", "cde" -> "abc_cde"
|
||||
"efg", "ghi" -> "efg_ghi"
|
||||
else -> "other"
|
||||
}
|
||||
}
|
||||
|
||||
fun box() : String {
|
||||
assertEquals("abc_cde", foo("abc"))
|
||||
assertEquals("abc_cde", foo("cde"))
|
||||
assertEquals("efg_ghi", foo("efg"))
|
||||
assertEquals("efg_ghi", foo("ghi"))
|
||||
|
||||
assertEquals("other", foo("xyz"))
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
fun foo(x : String) : String {
|
||||
assert("abz]".hashCode() == "aby|".hashCode())
|
||||
|
||||
when (x) {
|
||||
"abz]", "cde" -> return "abz_cde"
|
||||
"aby|", "ghi", "abz]" -> return "aby_ghi"
|
||||
}
|
||||
|
||||
return "other"
|
||||
}
|
||||
|
||||
fun box() : String {
|
||||
assertEquals("abz_cde", foo("abz]"))
|
||||
assertEquals("abz_cde", foo("cde"))
|
||||
assertEquals("aby_ghi", foo("aby|"))
|
||||
assertEquals("aby_ghi", foo("ghi"))
|
||||
|
||||
assertEquals("other", foo("xyz"))
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
fun foo1(x : String) : String {
|
||||
when (x) {
|
||||
"abc", "cde" -> return "abc_cde"
|
||||
"efg", "ghi" -> return "efg_ghi"
|
||||
}
|
||||
|
||||
return "other"
|
||||
}
|
||||
|
||||
fun foo2(x : String) : String {
|
||||
when (x) {
|
||||
"abc", "cde" -> return "abc_cde"
|
||||
"efg", "ghi" -> return "efg_ghi"
|
||||
else -> return "other"
|
||||
}
|
||||
}
|
||||
|
||||
fun box() : String {
|
||||
//foo1
|
||||
assertEquals("abc_cde", foo1("abc"))
|
||||
assertEquals("abc_cde", foo1("cde"))
|
||||
assertEquals("efg_ghi", foo1("efg"))
|
||||
assertEquals("efg_ghi", foo1("ghi"))
|
||||
|
||||
assertEquals("other", foo1("xyz"))
|
||||
|
||||
//foo2
|
||||
assertEquals("abc_cde", foo2("abc"))
|
||||
assertEquals("abc_cde", foo2("cde"))
|
||||
assertEquals("efg_ghi", foo2("efg"))
|
||||
assertEquals("efg_ghi", foo2("ghi"))
|
||||
|
||||
assertEquals("other", foo2("xyz"))
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
|
||||
fun foo() : Int {
|
||||
val x : String = "dsa"
|
||||
when (x) {
|
||||
"a" -> return 1
|
||||
"b" -> return 1
|
||||
"c" -> return 1
|
||||
"d" -> return 1
|
||||
"e" -> return 1
|
||||
"f" -> return 1
|
||||
else -> return -1
|
||||
}
|
||||
}
|
||||
|
||||
// 1 TABLESWITCH
|
||||
@@ -0,0 +1,11 @@
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
fun foo(x : String) : String {
|
||||
when (x) {
|
||||
"abc" -> return "abc"
|
||||
"efg", "ghi", "abc" -> return "efg_ghi"
|
||||
else -> return "other"
|
||||
}
|
||||
}
|
||||
|
||||
// 1 LOOKUPSWITCH
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
fun foo(x : String) : String {
|
||||
assert("abz]".hashCode() == "aby|".hashCode())
|
||||
|
||||
when (x) {
|
||||
"abz]" -> return "abz"
|
||||
"ghi" -> return "ghi"
|
||||
"aby|" -> return "aby"
|
||||
"abz]" -> return "fail"
|
||||
}
|
||||
|
||||
return "other"
|
||||
}
|
||||
|
||||
// 1 LOOKUPSWITCH
|
||||
@@ -0,0 +1,9 @@
|
||||
fun foo(x : String) : String {
|
||||
return when (x) {
|
||||
"abc", "cde" -> "abc_cde"
|
||||
"efg", "ghi" -> "efg_ghi"
|
||||
else -> "other"
|
||||
}
|
||||
}
|
||||
|
||||
// 1 LOOKUPSWITCH
|
||||
@@ -0,0 +1,11 @@
|
||||
fun foo(x : String) : String {
|
||||
val y = "cde"
|
||||
when (x) {
|
||||
"abc", "${y}" -> return "abc_cde"
|
||||
"e" + "fg", "ghi" -> return "efg_ghi"
|
||||
}
|
||||
|
||||
return "other"
|
||||
}
|
||||
|
||||
// 1 LOOKUPSWITCH
|
||||
@@ -0,0 +1,12 @@
|
||||
fun foo(x : String) : String {
|
||||
assert("abz]".hashCode() == "aby|".hashCode())
|
||||
|
||||
when (x) {
|
||||
"abz]", "cde" -> return "abz_cde"
|
||||
"aby|", "ghi" -> return "aby_ghi"
|
||||
}
|
||||
|
||||
return "other"
|
||||
}
|
||||
|
||||
// 1 LOOKUPSWITCH
|
||||
@@ -0,0 +1,19 @@
|
||||
fun foo1(x : String) : String {
|
||||
when (x) {
|
||||
"abc", "cde" -> return "abc_cde"
|
||||
"efg", "ghi" -> return "efg_ghi"
|
||||
}
|
||||
|
||||
return "other"
|
||||
}
|
||||
|
||||
fun foo2(x : String) : String {
|
||||
when (x) {
|
||||
"abc", "cde" -> return "abc_cde"
|
||||
"efg", "ghi" -> return "efg_ghi"
|
||||
else -> return "other"
|
||||
}
|
||||
}
|
||||
|
||||
// 2 LOOKUPSWITCH
|
||||
|
||||
@@ -31,7 +31,7 @@ import org.jetbrains.jet.codegen.AbstractBytecodeTextTest;
|
||||
/** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("compiler/testData/codegen/bytecodeText")
|
||||
@InnerTestClasses({BytecodeTextTestGenerated.BoxingOptimization.class, BytecodeTextTestGenerated.Constants.class, BytecodeTextTestGenerated.DirectInvoke.class, BytecodeTextTestGenerated.Statements.class, BytecodeTextTestGenerated.WhenEnumOptimization.class})
|
||||
@InnerTestClasses({BytecodeTextTestGenerated.BoxingOptimization.class, BytecodeTextTestGenerated.Constants.class, BytecodeTextTestGenerated.DirectInvoke.class, BytecodeTextTestGenerated.Statements.class, BytecodeTextTestGenerated.WhenEnumOptimization.class, BytecodeTextTestGenerated.WhenStringOptimization.class})
|
||||
public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
|
||||
@TestMetadata("accessorForProtected.kt")
|
||||
public void testAccessorForProtected() throws Exception {
|
||||
@@ -352,6 +352,49 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
|
||||
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/bytecodeText/whenStringOptimization")
|
||||
public static class WhenStringOptimization extends AbstractBytecodeTextTest {
|
||||
public void testAllFilesPresentInWhenStringOptimization() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("compiler/testData/codegen/bytecodeText/whenStringOptimization"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("denseHashCode.kt")
|
||||
public void testDenseHashCode() throws Exception {
|
||||
doTest("compiler/testData/codegen/bytecodeText/whenStringOptimization/denseHashCode.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("duplicatingItems.kt")
|
||||
public void testDuplicatingItems() throws Exception {
|
||||
doTest("compiler/testData/codegen/bytecodeText/whenStringOptimization/duplicatingItems.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("duplicatingItemsSameHashCode.kt")
|
||||
public void testDuplicatingItemsSameHashCode() throws Exception {
|
||||
doTest("compiler/testData/codegen/bytecodeText/whenStringOptimization/duplicatingItemsSameHashCode.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("expression.kt")
|
||||
public void testExpression() throws Exception {
|
||||
doTest("compiler/testData/codegen/bytecodeText/whenStringOptimization/expression.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nonInlinedConst.kt")
|
||||
public void testNonInlinedConst() throws Exception {
|
||||
doTest("compiler/testData/codegen/bytecodeText/whenStringOptimization/nonInlinedConst.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("sameHashCode.kt")
|
||||
public void testSameHashCode() throws Exception {
|
||||
doTest("compiler/testData/codegen/bytecodeText/whenStringOptimization/sameHashCode.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("statement.kt")
|
||||
public void testStatement() throws Exception {
|
||||
doTest("compiler/testData/codegen/bytecodeText/whenStringOptimization/statement.kt");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static Test suite() {
|
||||
TestSuite suite = new TestSuite("BytecodeTextTestGenerated");
|
||||
suite.addTestSuite(BytecodeTextTestGenerated.class);
|
||||
@@ -360,6 +403,7 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
|
||||
suite.addTestSuite(DirectInvoke.class);
|
||||
suite.addTestSuite(Statements.class);
|
||||
suite.addTestSuite(WhenEnumOptimization.class);
|
||||
suite.addTestSuite(WhenStringOptimization.class);
|
||||
return suite;
|
||||
}
|
||||
}
|
||||
|
||||
+35
-1
@@ -31,7 +31,7 @@ import org.jetbrains.jet.codegen.generated.AbstractBlackBoxCodegenTest;
|
||||
/** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("compiler/testData/codegen/boxWithStdlib")
|
||||
@InnerTestClasses({BlackBoxWithStdlibCodegenTestGenerated.Annotations.class, BlackBoxWithStdlibCodegenTestGenerated.Arrays.class, BlackBoxWithStdlibCodegenTestGenerated.BoxingOptimization.class, BlackBoxWithStdlibCodegenTestGenerated.CallableReference.class, BlackBoxWithStdlibCodegenTestGenerated.Casts.class, BlackBoxWithStdlibCodegenTestGenerated.DataClasses.class, BlackBoxWithStdlibCodegenTestGenerated.Evaluate.class, BlackBoxWithStdlibCodegenTestGenerated.FullJdk.class, BlackBoxWithStdlibCodegenTestGenerated.HashPMap.class, BlackBoxWithStdlibCodegenTestGenerated.JdkAnnotations.class, BlackBoxWithStdlibCodegenTestGenerated.PlatformNames.class, BlackBoxWithStdlibCodegenTestGenerated.Ranges.class, BlackBoxWithStdlibCodegenTestGenerated.Reflection.class, BlackBoxWithStdlibCodegenTestGenerated.Regressions.class, BlackBoxWithStdlibCodegenTestGenerated.Strings.class, BlackBoxWithStdlibCodegenTestGenerated.ToArray.class, BlackBoxWithStdlibCodegenTestGenerated.Vararg.class, BlackBoxWithStdlibCodegenTestGenerated.When.class, BlackBoxWithStdlibCodegenTestGenerated.WhenEnumOptimization.class})
|
||||
@InnerTestClasses({BlackBoxWithStdlibCodegenTestGenerated.Annotations.class, BlackBoxWithStdlibCodegenTestGenerated.Arrays.class, BlackBoxWithStdlibCodegenTestGenerated.BoxingOptimization.class, BlackBoxWithStdlibCodegenTestGenerated.CallableReference.class, BlackBoxWithStdlibCodegenTestGenerated.Casts.class, BlackBoxWithStdlibCodegenTestGenerated.DataClasses.class, BlackBoxWithStdlibCodegenTestGenerated.Evaluate.class, BlackBoxWithStdlibCodegenTestGenerated.FullJdk.class, BlackBoxWithStdlibCodegenTestGenerated.HashPMap.class, BlackBoxWithStdlibCodegenTestGenerated.JdkAnnotations.class, BlackBoxWithStdlibCodegenTestGenerated.PlatformNames.class, BlackBoxWithStdlibCodegenTestGenerated.Ranges.class, BlackBoxWithStdlibCodegenTestGenerated.Reflection.class, BlackBoxWithStdlibCodegenTestGenerated.Regressions.class, BlackBoxWithStdlibCodegenTestGenerated.Strings.class, BlackBoxWithStdlibCodegenTestGenerated.ToArray.class, BlackBoxWithStdlibCodegenTestGenerated.Vararg.class, BlackBoxWithStdlibCodegenTestGenerated.When.class, BlackBoxWithStdlibCodegenTestGenerated.WhenEnumOptimization.class, BlackBoxWithStdlibCodegenTestGenerated.WhenStringOptimization.class})
|
||||
public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
public void testAllFilesPresentInBoxWithStdlib() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("compiler/testData/codegen/boxWithStdlib"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
@@ -2005,6 +2005,39 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode
|
||||
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxWithStdlib/whenStringOptimization")
|
||||
public static class WhenStringOptimization extends AbstractBlackBoxCodegenTest {
|
||||
public void testAllFilesPresentInWhenStringOptimization() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("compiler/testData/codegen/boxWithStdlib/whenStringOptimization"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("duplicatingItems.kt")
|
||||
public void testDuplicatingItems() throws Exception {
|
||||
doTestWithStdlib("compiler/testData/codegen/boxWithStdlib/whenStringOptimization/duplicatingItems.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("duplicatingItemsSameHashCode.kt")
|
||||
public void testDuplicatingItemsSameHashCode() throws Exception {
|
||||
doTestWithStdlib("compiler/testData/codegen/boxWithStdlib/whenStringOptimization/duplicatingItemsSameHashCode.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("expression.kt")
|
||||
public void testExpression() throws Exception {
|
||||
doTestWithStdlib("compiler/testData/codegen/boxWithStdlib/whenStringOptimization/expression.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("sameHashCode.kt")
|
||||
public void testSameHashCode() throws Exception {
|
||||
doTestWithStdlib("compiler/testData/codegen/boxWithStdlib/whenStringOptimization/sameHashCode.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("statement.kt")
|
||||
public void testStatement() throws Exception {
|
||||
doTestWithStdlib("compiler/testData/codegen/boxWithStdlib/whenStringOptimization/statement.kt");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static Test suite() {
|
||||
TestSuite suite = new TestSuite("BlackBoxWithStdlibCodegenTestGenerated");
|
||||
suite.addTestSuite(BlackBoxWithStdlibCodegenTestGenerated.class);
|
||||
@@ -2027,6 +2060,7 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode
|
||||
suite.addTestSuite(Vararg.class);
|
||||
suite.addTestSuite(When.class);
|
||||
suite.addTestSuite(WhenEnumOptimization.class);
|
||||
suite.addTestSuite(WhenStringOptimization.class);
|
||||
return suite;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user