From ad14ee90616fe46aa1066260aa8aea684e0d7da5 Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Sun, 6 Apr 2014 14:35:18 +0400 Subject: [PATCH] Switch in when-expression: choice between lookupswitch and table switch (heuristically) --- .../jet/codegen/ExpressionCodegen.java | 35 +++++++++++++------ 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 82f880bffc3..50ae52818e1 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -20,13 +20,11 @@ import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.intellij.openapi.editor.Document; import com.intellij.openapi.progress.ProcessCanceledException; -import com.intellij.openapi.util.Pair; import com.intellij.psi.PsiElement; import com.intellij.psi.tree.IElementType; import com.intellij.util.ArrayUtil; import com.intellij.util.Function; import com.intellij.util.containers.Stack; -import com.sun.jdi.IntegerValue; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.resolve.constants.IntegerValueConstant; @@ -49,7 +47,6 @@ import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.calls.model.*; import org.jetbrains.jet.lang.resolve.calls.util.CallMaker; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; -import org.jetbrains.jet.lang.resolve.constants.IntValue; import org.jetbrains.jet.lang.resolve.constants.IntegerValueTypeConstant; import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants; import org.jetbrains.jet.lang.resolve.java.JvmAbi; @@ -3774,10 +3771,10 @@ The "returned" value of try expression with no finally is either the last expres } gen(expression.getSubjectExpression(), subjectType); - generateSwitchLookupCall( - transitions, - //if there is no else-entry and it's statement then default --- endLabel - (hasElse || !isStatement) ? elseLabel : endLabel + generateSwitchCall( + transitions, + //if there is no else-entry and it's statement then default --- endLabel + (hasElse || !isStatement) ? elseLabel : endLabel ); //resolving entries' labels @@ -3814,7 +3811,7 @@ The "returned" value of try expression with no finally is either the last expres return StackValue.onStack(resultType); } - private void generateSwitchLookupCall(Map transitions, Label defaultLabel) { + private void generateSwitchCall(Map transitions, Label defaultLabel) { int[] keys = new int[transitions.size()]; Label[] labels = new Label[transitions.size()]; int i = 0; @@ -3826,8 +3823,26 @@ The "returned" value of try expression with no finally is either the last expres i++; } - //switch code - v.lookupswitch(defaultLabel, keys, labels); + int hi = keys[keys.length-1]; + int lo = keys[0]; + long emptyCells = ((long)hi - (long)lo + 1) - keys.length; + + boolean useTableSwitch = keys.length > 0 && + 10L * emptyCells <= (long) keys.length; // less then 10% of empty cells + + if (!useTableSwitch) { + v.lookupswitch(defaultLabel, keys, labels); + return; + } + + Label[] sparseLabels = new Label[hi-lo + 1]; + Arrays.fill(sparseLabels, defaultLabel); + + for (i = 0; i < keys.length; i++) { + sparseLabels[keys[i] - lo] = labels[i]; + } + + v.tableswitch(lo, hi, defaultLabel, sparseLabels); } private boolean doesConstantFitForSwitch(CompileTimeConstant constant) {